//public override void EnterArgumentWithoutName([NotNull] SBP.ArgumentWithoutNameContext context) //{ // m_argumentIndex = m_expressionData.Peek().Count; //} //public override void ExitArgumentWithoutName([NotNull] SBP.ArgumentWithoutNameContext context) //{ // m_expressionData.Peek().Peek().ArgumentIndex = m_argumentIndex; //} public override void ExitReferenceArgument([NotNull] SBP.ReferenceArgumentContext context) { string name = context.children[1].GetText(); string refType = context.children[0].GetText(); m_expressionData.Push(SBExpressionData.CreateIdentifier(name, refType)); }
public override void ExitTypeReference([NotNull] SBP.TypeReferenceContext context) { var typename = context.GetChild(2).GetText(); var type = ParseTypeString(typename, false, true, (context.GetChild(2).Payload as Antlr4.Runtime.CommonToken)); m_expressionData.Push(SBExpressionData.Constant(TypeReference.TypeType, type)); }
private SBExpressionData ResolveQualifiedType(string identifier, bool reportUnresolved = false, IToken token = null) { if (identifier.Contains('.')) { string[] parts = identifier.Split('.'); int c = parts.Length; SBExpressionData result = this.ResolveSingleIdentifierType(parts[0], reportUnresolved, token); if (result != null) { for (int i = 1; i < c; i++) { result = this.ResolveDotIdentifier(result, SBExpressionData.CreateIdentifier(parts[i], token: token)); if (result == null) { return null; } } if (result != null) { return result; } } } else { return this.ResolveSingleIdentifierType(identifier, reportUnresolved, token); } return null; }
public override void ExitExpAwait([NotNull] SBP.ExpAwaitContext context) { try { var exp = this.ResolveForGetOperation(m_expressionData.Pop()); m_expressionData.Push(SBExpressionData.CreateAwaitExpression(exp.ExpressionCode, context.Start)); } catch { m_expressionData.Push(new SBExpressionData( SBExpressionType.OperationError, "Error parsing 'await' operation.", null, context.Start)); } //var awaiter = this.MakeAwaitOperation(exp.ExpressionCode, context, true); //if (awaiter != null) //{ // m_expressionData.Push( // new SBExpressionData( // HomeType.Immediate, // SBExpressionType.Expression, // new TypeReference(awaiter.Type), // awaiter)); //} //else //{ // m_expressionData.Push(exp); //} }
private SBExpressionData ResolveIdentifierForGetOperation(string input, bool inFunctionScope, TypeReference targetType = null) { SBExpressionData result = this.ResolveQualifiedIdentifier(input, inFunctionScope); if (result.IsError()) { return(result); } if (result != null) { Expression expression = result.ExpressionCode; var isContainer = typeof(IValueContainer).IsAssignableFrom(expression.Type); if (isContainer && (targetType == null || !targetType.Type.IsAssignableFrom(typeof(IValueContainer)))) { var datatype = expression.Type.GenericTypeArguments[0]; var getValue = Expression.Call( expression, expression.Type.GetMethod("GetTypedValue"), Expression.Constant(null, typeof(StepBro.Core.Logging.ILogger))); result = new SBExpressionData( HomeType.Immediate, SBExpressionType.Expression, (TypeReference)datatype, getValue); } return(result); } else { throw new NotImplementedException("Must be handled somewhere else!!"); } }
public override void ExitCallAssignment([NotNull] SBP.CallAssignmentContext context) { if (context.ChildCount == 1) { if (context.Start.Type == SBP.AWAIT) { m_callAssignmentAwait = true; return; } else if (context.Start.Type == SBP.START) { throw new NotImplementedException(); } else { throw new NotImplementedException(); } } else if (context.ChildCount == 3) { var child = context.GetChild(2) as Antlr4.Runtime.Tree.TerminalNodeImpl; if (child != null && child.Payload.Type == SBP.AWAIT) { m_callAssignmentAwait = true; } else { throw new NotImplementedException(); } } m_callAssignmentTarget = m_expressionData.Pop(); m_callAssignmentTarget = this.ResolveIfIdentifier(m_callAssignmentTarget, true); }
public SBExpressionData CreateListIndexerExpression(SBExpressionData source, SBExpressionData indexer) { var indexerCode = indexer.ExpressionCode; // http://stackoverflow.com/questions/794198/how-do-i-check-if-a-given-value-is-a-generic-list if (source.DataType.Type.IsGenericType && source.DataType.Type.GetGenericTypeDefinition() == typeof(List <>)) { if (indexer.DataType.Equals(typeof(long))) { indexerCode = Expression.Convert(indexerCode, typeof(int)); } else if (!indexer.DataType.Equals(typeof(int))) { throw new NotImplementedException("An indexer type not supported yet."); } var propInfo = source.DataType.Type.GetProperty("Item", source.DataType.Type.GenericTypeArguments[0], new Type[] { typeof(int) }); var propExpr = Expression.Property(source.ExpressionCode, propInfo, indexerCode); return(new SBExpressionData(propExpr, SBExpressionType.Indexing)); // http://stackoverflow.com/questions/6759416/accessing-indexer-from-expression-tree } else { throw new NotImplementedException(); } }
public override void ExitExpDotIdentifier([NotNull] SBP.ExpDotIdentifierContext context) { var left = m_expressionData.Pop(); left = this.ResolveIfIdentifier(left, true); if (left.IsUnresolvedIdentifier || left.IsError()) { m_expressionData.Push(new SBExpressionData( SBExpressionType.OperationError, "Error parsing 'dot' operation.", context.GetText(), new TokenOrSection(context.Start, context.Stop, context.GetText()))); } else { var child = context.GetChild(2) as TerminalNodeImpl; var identifier = SBExpressionData.CreateIdentifier(child.GetText(), token: child.Payload as CommonToken); var result = this.ResolveDotIdentifier(left, identifier); if (result == null) { var payload = context.GetChild(2).Payload as CommonToken; m_errors.SymanticError(payload.Line, payload.StartIndex, false, $"Unknown identifier: '{identifier.Value as string}'."); result = new SBExpressionData( SBExpressionType.OperationError, "Error parsing 'dot' operation.", context.GetText(), new TokenOrSection(context.Start, context.Stop, context.GetText())); } else if (result.IsError()) { var payload = context.GetChild(2).Payload as CommonToken; m_errors.SymanticError(payload.Line, payload.StartIndex, false, result.Argument); } m_expressionData.Push(result); } }
private SBExpressionData ResolveQualifiedIdentifier(string identifier, bool inFunctionScope, bool reportUnresolved = false, IToken token = null) { if (String.IsNullOrWhiteSpace(identifier)) throw new ArgumentException("Empty identifier string."); if (identifier.Contains('.')) { string[] parts = identifier.Split('.'); int c = parts.Length; SBExpressionData result = this.ResolveSingleIdentifier(parts[0], inFunctionScope, reportUnresolved, token); if (result != null) { for (int i = 1; i < c; i++) { result = this.ResolveDotIdentifier(result, SBExpressionData.CreateIdentifier(parts[i], token: token)); if (result == null) { return null; } } } return result; } else { return this.ResolveSingleIdentifier(identifier, inFunctionScope, reportUnresolved, token); } }
public ProcedureVariable AddVariable(string name, TypeReference type, SBExpressionData assignment, EntryModifiers modifiers) { var v = new ProcedureVariable(false, name, type, modifiers); v.Assignment = assignment; m_localVariables.Add(v); return(v); }
//private TSExpressionData ResolveDotIdentifierLocalVariableReference(TSExpressionData left, string right) //{ // throw new NotImplementedException(); //} private SBExpressionData ResolveDotIdentifierTypeReference(SBExpressionData left, SBExpressionData right) { var leftType = left.DataType.Type; var rightString = right.Value as string; if (leftType.IsEnum) { try { var value = Enum.Parse(leftType, rightString); return new SBExpressionData(HomeType.Immediate, SBExpressionType.Constant, left.DataType, Expression.Constant(value), value, token: right.Token); } catch { // Not found in the value list. return new SBExpressionData( SBExpressionType.UnknownIdentifier, $"Nonexisting enum value '{rightString}' for enum type '{leftType.Name}'.", rightString, right.Token); } } else if (leftType.IsTypeDefinition) { var methods = leftType.GetMethods().Where(mi => mi.Name == rightString).ToList(); methods.AddRange(m_addonManager.ListExtensionMethods(leftType).Where(mi => mi.Name == rightString)); if (methods.Count > 0) { return new SBExpressionData( HomeType.Immediate, SBExpressionType.MethodReference, // Expression type left.DataType, // Data type left.ExpressionCode, // The instance expression methods, // The method list token: right.Token); } var properties = leftType.GetProperties().Where(pi => String.Equals(pi.Name, rightString, StringComparison.InvariantCulture)).ToArray(); if (properties.Length == 1) { return new SBExpressionData( HomeType.Immediate, SBExpressionType.PropertyReference, // Expression type (TypeReference)properties[0].PropertyType, // Data type Expression.Property(null, properties[0]), // The property access expression properties[0], // Reference to the property info token: right.Token); } else if (properties.Length > 1) { m_errors.SymanticError(right.Token.Line, right.Token.Column, false, $"More than one property with same name: \"{rightString}\"."); return null; } return null; // None found } else { throw new NotImplementedException(); } }
public override void EnterMethodArguments([NotNull] SBP.MethodArgumentsContext context) { var left = m_expressionData.Pop(); left = this.ResolveIfIdentifier(left, true); m_leftOfMethodCallExpression = left; m_expressionData.Push(left); }
public override void ExitVariableInitializerExpression([NotNull] SBP.VariableInitializerExpressionContext context) { var stack = m_expressionData.PopStackLevel(); m_variableInitializer = this.ResolveForGetOperation(stack.Pop()); if (m_variableInitializer.IsError()) { m_errors.UnresolvedIdentifier(m_variableInitializer.Token.Line, m_variableInitializer.Token.Column, m_variableInitializer.Value as string); } }
private SBExpressionData ResolveSingleIdentifierType(string identifier, bool reportUnresolved = false, IToken token = null) { IIdentifierInfo foundIdentifier = null; if (m_file != null) { var identifiers = m_file.LookupIdentifier(identifier); if (identifiers != null) { if (identifiers.Count > 1) { throw new ParsingErrorException((token != null) ? token.Line : -1, identifier, "More than one alternative. "); } return this.IdentifierToExpressionData(identifiers[0], token); } foundIdentifier = this.TryGetFileElementInScope(m_file?.Usings, identifier); // File elements can also act as types. if (foundIdentifier != null) { return this.IdentifierToExpressionData(foundIdentifier, token); } #region TBD foreach (var nsUsing in m_file.ListResolvedNamespaceUsings()) { var foundViaUsing = this.ResolveDotIdentifier(nsUsing, SBExpressionData.CreateIdentifier(identifier, token: token)); if (foundViaUsing != null) { return foundViaUsing; } } #endregion } if (m_addonManager != null) { foundIdentifier = m_addonManager.Lookup(m_file?.Usings, identifier); if (foundIdentifier != null) { return this.IdentifierToExpressionData(foundIdentifier, token); } } if (reportUnresolved) { if (token != null) { m_errors.UnresolvedType(token.Line, token.Column, identifier); } else { m_errors.UnresolvedType(-1, -1, identifier); } } return null; }
// Checks if the current context is an identifier, and pushes it to the expression stack. private void PushIfIdentifier(ParserRuleContext context) { if (context.ChildCount == 1) { var child = context.GetChild(0) as TerminalNodeImpl; if (child != null && child.Payload.Type == SBP.IDENTIFIER) { m_expressionData.Push(SBExpressionData.CreateIdentifier(context.GetText(), token: child.Payload as CommonToken)); } } }
//private TSExpressionData ResolveDotIdentifierIdentifier(TSExpressionData left, string right) //{ // throw new NotSupportedException("Don't think this is supposed to be called ever."); //} private SBExpressionData ResolveDotIdentifierGlobalVariableReference(SBExpressionData left, SBExpressionData right) { var datatype = left.DataType.Type.GenericTypeArguments[0]; var getValue = Expression.Call( left.ExpressionCode, left.DataType.Type.GetMethod("GetTypedValue"), Expression.Constant(null, typeof(StepBro.Core.Logging.ILogger))); var instance = new SBExpressionData( HomeType.Immediate, SBExpressionType.Expression, (TypeReference)datatype, getValue, left.Value); return this.ResolveDotIdentifierInstanceReference(instance, right, true); }
public SBExpressionData ResolveIfIdentifier(SBExpressionData input, bool inFunctionScope, TypeReference targetType = null) { if (input.IsUnresolvedIdentifier) { string identifier = (string)input.Value; SBExpressionData result = this.ResolveQualifiedIdentifier(identifier, inFunctionScope, true, input.Token); if (result != null) { // Preserve some of the extra data from input. result.Token = input.Token; result.ParameterName = input.ParameterName; result.Argument = input.Argument; return result; } } return input; }
public override void ExitVariableDeclaratorWithoutAssignment([NotNull] SBP.VariableDeclaratorWithoutAssignmentContext context) { if (m_variableType != null) { if (m_variableType.Type.IsValueType) { m_variableInitializer = SBExpressionData.Constant(m_variableType, Activator.CreateInstance(m_variableType.Type)); } else if (m_variableType.Type == typeof(string)) { m_variableInitializer = SBExpressionData.Constant(m_variableType, null); } else if (m_variableType.Type.IsClass) { throw new NotImplementedException(); } } }
public override void ExitPrimary([NotNull] SBP.PrimaryContext context) { if (context.Start.Type == Grammar.StepBro.IDENTIFIER) { m_expressionData.Push(SBExpressionData.CreateIdentifier(context.GetText(), token: context.Start)); } else if (context.Start.Type == Grammar.StepBro.THIS) { var thisProperty = Expression.Property( m_currentProcedure.ContextReferenceInternal, typeof(IScriptCallContext).GetProperty(nameof(IScriptCallContext.This))); m_expressionData.Push(new SBExpressionData( HomeType.Immediate, SBExpressionType.PropertyReference, new TypeReference(typeof(IProcedureThis)), thisProperty, token: context.Start)); } }
private SBExpressionData ResolveForGetOperation(SBExpressionData input, TypeReference targetType = null, bool reportIfUnresolved = false) { var output = input; if (input.IsUnresolvedIdentifier) { var resolved = this.ResolveIdentifierForGetOperation((string)input.Value, m_inFunctionScope, targetType); if (resolved != null) { output = resolved; output.Token = input.Token; output.ParameterName = input.ParameterName; output.Argument = input.Argument; if (reportIfUnresolved && resolved.IsUnknownIdentifier) { m_errors.UnresolvedIdentifier(output.Token, (string)output.Value); } } } return(output); }
private SBExpressionData ResolveDotIdentifierNamespace(SBExpressionData left, SBExpressionData right) { NamespaceList subs = null; var rightString = right.Value as string; if (left.NamespaceList.TryGetSubList(rightString, ref subs)) { return new SBExpressionData(HomeType.Immediate, SBExpressionType.Namespace, null, null, subs); } else { var type = left.NamespaceList.ListTypes(false).FirstOrDefault(ti => ti.Name == rightString); if (type != null) { return new SBExpressionData(HomeType.Immediate, SBExpressionType.TypeReference, (TypeReference)type, token: right.Token); } else { //throw new Exception("Sub-namespace was not found (" + right + ")."); return null; } } }
public override void EnterLambdaExpression([NotNull] SBP.LambdaExpressionContext context) { m_lambdaDelegateTargetType = null; m_lambdaDelegateGenericArguments = null; m_lambdaDelegateReturnType = null; m_lambdaLeftExpression = null; m_lambdaParentRule = context.Parent.Parent.RuleIndex; m_lambdaTypedParameters = null; switch (m_lambdaParentRule) { case SBP.RULE_argument: m_lambdaLeftExpression = m_leftOfMethodCallExpression; break; case SBP.RULE_variableInitializer: break; default: throw new NotImplementedException(); } }
private SBExpressionData ResolveDotIdentifier(IIdentifierInfo left, SBExpressionData right) { SBExpressionData leftAsExpData = null; switch (left.Type) { case IdentifierType.UnresolvedType: throw new NotImplementedException(); // TODO: Handle error case IdentifierType.DotNetNamespace: leftAsExpData = new SBExpressionData(HomeType.Immediate, SBExpressionType.Namespace, null, null, left.Reference); break; case IdentifierType.DotNetType: leftAsExpData = new SBExpressionData(HomeType.Immediate, SBExpressionType.TypeReference, left.DataType); break; //case IdentifierType.FileByName: // break; case IdentifierType.FileNamespace: leftAsExpData = new SBExpressionData(HomeType.Immediate, SBExpressionType.ScriptNamespace, null, null, left.Reference); break; default: throw new NotImplementedException(); } return this.ResolveDotIdentifier(leftAsExpData, right); }
private SBExpressionData ResolveDotIdentifier(SBExpressionData left, SBExpressionData right) { SBExpressionData result = null; switch (left.ReferencedType) { case SBExpressionType.Namespace: result = this.ResolveDotIdentifierNamespace(left, right); break; case SBExpressionType.GlobalVariableReference: result = this.ResolveDotIdentifierGlobalVariableReference(left, right); break; case SBExpressionType.Identifier: //throw new NotSupportedException("Don't think this is supposed to be called ever."); //result = this.ResolveDotIdentifierIdentifier(left, right); //break; case SBExpressionType.Constant: case SBExpressionType.Expression: case SBExpressionType.Indexing: case SBExpressionType.LocalVariableReference: case SBExpressionType.PropertyReference: case SBExpressionType.TestListReference: result = this.ResolveDotIdentifierInstanceReference(left, right, true); break; case SBExpressionType.TypeReference: result = this.ResolveDotIdentifierTypeReference(left, right); break; case SBExpressionType.ScriptNamespace: case SBExpressionType.ProcedureReference: result = this.ResolveDotIdentifierInstanceReference(left, right, true); break; default: throw new Exception("Illegal left side of dot-operator; " + left.ToString()); } return result; }
public void Push(SBExpressionData data) { //System.Diagnostics.Debug.WriteLine("Push: " + data.ToString()); m_expressionData.Peek().Push(data); }
public override void ExitUsingExpression([NotNull] SBP.UsingExpressionContext context) { //var usingVariable = m_scopeStack.Peek().AddVariable("usingVariable_" + context.start.Line.ToString(), typeof(IDisposable), null, EntryModifiers.Private); Expression usingExpression = null; var child = context.GetChild(0) as Antlr4.Runtime.RuleContext; if (child.RuleIndex == SBP.RULE_simpleVariableDeclaration) { if (m_variableInitializer.IsConstant && m_variableInitializer.Value == null) { // Convert the null value to the type of the variable if (m_variableType.Type == typeof(string)) { m_variableInitializer = new SBExpressionData(TypeReference.TypeString, null); } } if (m_variableType == null) { throw new NotImplementedException(); } else if (m_variableType.Type != typeof(VarSpecifiedType)) { if (m_variableInitializer.IsValueType && m_variableInitializer.IsConstant && m_variableInitializer.Value == null) { m_variableInitializer.NarrowGetValueType(m_variableType); } else if (m_variableType != m_variableInitializer.DataType && !m_variableType.Type.IsAssignableFrom(m_variableInitializer.DataType.Type)) { throw new NotImplementedException("Convertion of variable initializer is not implemented."); } } if (m_variableType.Type == typeof(VarSpecifiedType)) { m_variableType = m_variableInitializer.DataType; } var scope = m_scopeStack.Peek(); var v = scope.AddVariable(m_variableName, m_variableType, null, EntryModifiers.Private); usingExpression = Expression.Assign(v.VariableExpression, m_variableInitializer.ExpressionCode); m_variableName = null; m_variableInitializer = null; } else if (child.RuleIndex == SBP.RULE_expression) { var stack = m_expressionData.PopStackLevel(); var exp = stack.Pop(); exp = this.ResolveForGetOperation(exp); if (!exp.IsValueType) { throw new NotImplementedException("Something wrong with the using expression; it is not an IDisposable type."); } usingExpression = exp.ExpressionCode; } else { throw new NotImplementedException(String.Format("What? Unknown using expression type (rule = {0}).", child.RuleIndex)); } if ((!usingExpression.Type.IsClass && !usingExpression.Type.IsInterface) || !typeof(IDisposable).IsAssignableFrom(usingExpression.Type)) { throw new NotImplementedException("Something wrong with the using expression; it is not an IDisposable type."); } m_scopeStack.Peek().UsingVariableAssignment = usingExpression; // Save for later }
public override void EnterCallStatement([NotNull] SBP.CallStatementContext context) { this.AddEnterStatement(context); m_callAssignmentTarget = null; m_callAssignmentAwait = false; }
public override void ExitVariableDeclarator([NotNull] SBP.VariableDeclaratorContext context) { if (m_variableType != null) { //m_variableInitializer = ResolveIfIdentifier(m_variableInitializer, m_inFunctionScope); if (m_variableInitializer.IsError()) { if (m_variableType.Type != typeof(VarSpecifiedType)) { object def = null; if (m_variableType.Type.IsValueType) { def = Activator.CreateInstance(m_variableType.Type); } m_variableInitializer = SBExpressionData.Constant(m_variableType, def); } else { // Just set the type to 'object' then. m_variableInitializer = SBExpressionData.Constant(TypeReference.TypeObject, null); } } if (m_variableInitializer.IsConstant && m_variableInitializer.Value == null) { // Convert the null value to the type of the variable if (m_variableType.Type == typeof(string)) { m_variableInitializer = SBExpressionData.Constant(TypeReference.TypeString, null); } } else if (m_variableInitializer.IsAwaitExpression) { m_variableInitializer = new SBExpressionData( this.MakeAwaitOperation( m_variableInitializer.ExpressionCode, context, true, m_variableType.Type)); } if (m_variableType.Type != typeof(VarSpecifiedType)) { if (m_variableInitializer.IsValueType && m_variableInitializer.IsConstant && m_variableInitializer.Value == null) { m_variableInitializer.NarrowGetValueType(m_variableType); } else if (m_variableType != m_variableInitializer.DataType && !m_variableType.Type.IsAssignableFrom(m_variableInitializer.DataType.Type)) { m_variableInitializer = this.CastProcedureAssignmentArgumentIfNeeded(m_variableType, m_variableInitializer); if (m_variableInitializer.DataType.Type != m_variableType.Type) { if (m_variableInitializer.DataType.Type == typeof(object) && m_variableInitializer.SuggestsAutomaticTypeConversion) { m_variableInitializer = new SBExpressionData( Expression.Convert(m_variableInitializer.ExpressionCode, m_variableType.Type)); } else { m_variableInitializer.NarrowGetValueType(); if (m_variableInitializer.DataType.Type != m_variableType.Type) { //m_errors.SymanticError(context.Start.Line, context.Start.Column, false, ""); throw new ParsingErrorException(context.Start.Line, "Data Type", "Convertion of variable initializer is not implemented."); } } } } } m_variables.Add( new NamedData <SBExpressionData>( m_variableName, m_variableInitializer)); m_variableName = null; m_variableInitializer = null; } }
public SBExpressionData CastProcedureAssignmentArgumentIfNeeded(TypeReference type, SBExpressionData expression) { var t = type.Type; if (!expression.IsError() && expression.DataType.Type != t && expression.DataType.Type == typeof(IProcedureReference) && t.IsConstructedGenericType && t.GenericTypeArguments.Length == 1 && t.GetGenericTypeDefinition() == typeof(IProcedureReference <>)) { var getCastMethodTyped = s_CastProcedureReference.MakeGenericMethod(t.GenericTypeArguments[0]); var casted = Expression.Call( getCastMethodTyped, m_currentProcedure.ContextReferenceInternal, expression.ExpressionCode); return(new SBExpressionData(casted)); } else { return(expression); } }
public override void ExitLiteralNull([NotNull] SBP.LiteralNullContext context) { m_expressionData.Push(SBExpressionData.Constant((TypeReference)typeof(object), null, context.Start)); }