private IValue InterpretCastExpression(SyneryParser.CastExpressionContext context) { IValue left = InterpretExpression(context.expression()); SyneryType conversionType = Controller.Interpret <SyneryParser.PrimitiveTypeContext, SyneryType>(context.primitiveType()); if (left.Value != null) { // try to cast the given value. try { object result; result = Convert.ChangeType(left.Value, conversionType.UnterlyingDotNetType); return(new TypedValue(conversionType, result)); } catch (Exception) { throw new SyneryInterpretationException(context, string.Format("Error with cast expression '{0}'. Cannot cast the value '{1}' of type '{2}' to new type '{3}'.", context.GetText(), left.Value, left.Type.PublicName, conversionType.PublicName)); } } else { // the given value is NULL. // create a new TypedValue with the given type and a NULL value return(new TypedValue(conversionType, null)); } }
/// <summary> /// Creates a field using the given parameters and adds it to the list of fields /// </summary> /// <param name="name"></param> /// <param name="type"></param> /// <param name="parentType"></param> /// <param name="defaultValue"></param> /// <returns></returns> private IRecordTypeField AddFieldWithParentType(string name, SyneryType type, IRecordType parentType, IValue defaultValue = null) { IRecordTypeField field = new RecordTypeField(parentType) { Name = name, Type = type, DefaultValue = defaultValue, }; _Fields.Add(field); return(field); }
/// <summary> /// Gets the symbol name of a primitive type (e.g. "STRING") or complex type (e.g. "Person" for a "#Person" Record Type). /// </summary> /// <param name="syneryType"></param> /// <returns></returns> public static string GetSyneryTypeSymbol(SyneryType syneryType) { if (String.IsNullOrEmpty(syneryType.Name)) { // it seems to be a primitive type .NET CLR type return(GetSyneryTypeSymbol(syneryType.UnterlyingDotNetType)); } else { // it seems to be a complex type (e.g. Record Type) return(syneryType.Name); } }
private ExpressionValue GetLibraryPluginVariableValueExpression(SyneryParser.LibraryPluginVariableReferenceContext context) { string libraryPluginIdentifier; string variableIdentifier; string fullIdentifier = context.ExternalLibraryIdentifier().GetText(); // split the identifier bool success = FunctionHelper.FragmentLibraryPluginIdentifier(fullIdentifier, out libraryPluginIdentifier, out variableIdentifier); if (success == false) { throw new SyneryInterpretationException(context, "Wasn't able to fragment the library plugin variable identifier. It doesn't have the expected format."); } // validate the identifer if (String.IsNullOrEmpty(libraryPluginIdentifier)) { throw new SyneryInterpretationException(context, "The library plugin identifer is empty."); } if (String.IsNullOrEmpty(variableIdentifier)) { throw new SyneryInterpretationException(context, "The variable identifer is empty."); } // find the variable declaration IStaticExtensionVariableData variableData = Memory.LibraryPluginManager.GetStaticVariableDataByIdentifier(libraryPluginIdentifier, variableIdentifier); // create an expression that calls a method on LibraryPluginManager that looks like these: // Memory.LibraryPluginManager.GetStaticVariableWithPrimitiveReturn(variableData) MethodInfo executeFunctionMethod = typeof(ILibraryPluginManager) .GetMethod("GetStaticVariableWithPrimitiveReturn", new Type[] { typeof(IStaticExtensionVariableData) }); Expression libraryPluginManagerExpression = Expression.Constant(Memory.LibraryPluginManager); Expression paramFunctionDataExpression = Expression.Constant(variableData, typeof(IStaticExtensionVariableData)); Expression methodCallExpression = Expression.Call( libraryPluginManagerExpression, executeFunctionMethod, paramFunctionDataExpression); SyneryType resultType = TypeHelper.GetSyneryType(variableData.Type); return(new ExpressionValue( expression: methodCallExpression, resultType: resultType)); }
private void InterpretDeclaration(SyneryParser.VariableDeclartionContext context) { SyneryType type = Controller.Interpret <SyneryParser.TypeContext, SyneryType>(context.type()); foreach (var assignment in context.variableAssignment()) { if (assignment.variableReference() != null) { string name = assignment.variableReference().GetText(); // create new variable in scope Memory.CurrentScope.DeclareVariable(name, type); InterpretAssignment(assignment); } } }
/// <summary> /// Creates an Expression that casts a value into an other type. /// </summary> /// <param name="context"></param> /// <param name="queryMemory"></param> /// <returns></returns> private IExpressionValue InterpretCastExpression(SyneryParser.RequestCastExpressionContext context, QueryMemory queryMemory) { IExpressionValue left = InterpretRequestExpression(context.requestExpression(), queryMemory); SyneryType targetSyneryType = Controller.Interpret <SyneryParser.PrimitiveTypeContext, SyneryType>(context.primitiveType()); Type targetConversionType = targetSyneryType.UnterlyingDotNetType; // create an Expression that calls the Convert.ChangeType(value, type); method MethodInfo convetToString = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(Type) }); Expression changeTypeExpression = Expression.Call(convetToString, Expression.Convert(left.Expression, typeof(object)), Expression.Constant(targetConversionType)); Expression fieldExpression = Expression.Convert(changeTypeExpression, targetConversionType); return(new ExpressionValue( resultType: targetSyneryType, expression: fieldExpression )); }
/// <summary> /// Checks whether the given SyneryType is a primitive .NET CLR type. /// An opposite of a primitive type for example would be a Record Type. /// </summary> /// <param name="syneryType"></param> /// <returns></returns> public static bool IsPrimitiveType(SyneryType syneryType) { return(SUPPORTED_DOTNET_TYPES.Contains(syneryType.UnterlyingDotNetType)); }
public ExpressionValue(Expression expression, SyneryType resultType) { Expression = expression; ResultType = resultType; }
/// <summary> /// Tries to find the function declaration with the matching function signature. It also considers that a parameter /// isn't set because a default value is available /// /// EXAMPLE: /// /// myFunc(string first, string second = "default") /// // do something... /// END /// /// // call with one parameter /// myFunc("first parameter"); /// </summary> /// <param name="memory">the SyneryMemory that contains a list with all available functions.</param> /// <param name="identifier">the name of the function</param> /// <param name="listOfParameterTypes">the types of all available parameters</param> /// <returns></returns> public static IFunctionData FindSyneryFunctionDeclaration(ISyneryMemory memory, string identifier, SyneryType[] listOfParameterTypes) { // try to find function(s) with the same name with at least the same number of parameters as given IEnumerable <IFunctionData> listOfFunctionData = from f in memory.Functions where f.FullName == IdentifierHelper.GetIdentifierBasedOnFunctionScope(memory, identifier) && f.FunctionDefinition.Parameters.Count >= listOfParameterTypes.Count() select f; // try to find the matching function signature // also consider that a parameter isn't set because a default value is available foreach (IFunctionData data in listOfFunctionData) { bool isMatching = true; for (int i = 0; i < data.FunctionDefinition.Parameters.Count; i++) { if (listOfParameterTypes.Count() > i && listOfParameterTypes[i] != null) { SyneryType expectedType = data.FunctionDefinition.Parameters[i].Type; SyneryType givenType = listOfParameterTypes[i]; // compare the types of the expected parameter and the given value if (givenType != expectedType) { // maybe these are two record-types which derive from each other if (givenType.UnterlyingDotNetType != typeof(IRecord) || expectedType.UnterlyingDotNetType != typeof(IRecord)) { isMatching = false; } else { string expectedTypeName = IdentifierHelper.GetFullName(expectedType.Name, data.CodeFileAlias); if (!RecordHelper.IsDerivedType(memory, givenType.Name, expectedTypeName)) { isMatching = false; } } } } else { // no value given for the parameter: check whether there is a default value if (data.FunctionDefinition.Parameters[i].DefaultValue == null) { isMatching = false; } } } // the current function declaration seems to match -> return it if (isMatching == true) { return(data); } } // no matching function declaration found return(null); }
public TypedValue(SyneryType syneryType, object value = null) { Value = value; Type = syneryType; }
/// <summary> /// Creates a new field declaration and adds it to the record type. /// </summary> /// <param name="name"></param> /// <param name="type"></param> /// <param name="defaultValue"></param> /// <returns></returns> public IRecordTypeField AddField(string name, SyneryType type, IValue defaultValue = null) { return(AddFieldWithParentType(name, type, this, defaultValue)); }
/// <summary> /// Executes the function from the given <paramref name="functionData"/> using the given <paramref name="controller"/> and by setting the <paramref name="listOfParameters"/> as local scope variables. /// </summary> /// <param name="controller">the controller that is used to interpret the function</param> /// <param name="functionData">contains the data for the function that should be executed</param> /// <param name="listOfParameters"></param> /// <param name="functionCallContext">the synery context where the function is called (only used in exceptions)</param> /// <returns>the return value may be null if the function definition says HasReturnValue=false</returns> public static IValue ExecuteSyneryFunction(IInterpretationController controller, IFunctionData functionData, object[] listOfParameters, Antlr4.Runtime.ParserRuleContext functionCallContext) { IValue returnValue; IDictionary <string, IValue> scopeVariables = new Dictionary <string, IValue>(); int sizeOfSignatureParameters = functionData.FunctionDefinition.Parameters.Count; int sizeOfListOfParameters = listOfParameters.Count(); // prepare the parameters as local scope variables for (int i = 0; i < sizeOfSignatureParameters; i++) { object variableValue = null; string variableName = functionData.FunctionDefinition.Parameters[i].Name; SyneryType variableType = functionData.FunctionDefinition.Parameters[i].Type; if (sizeOfListOfParameters >= (i + 1) && listOfParameters[i] != null) { variableValue = listOfParameters[i]; } else if (functionData.FunctionDefinition.Parameters[i].DefaultValue != null) { variableValue = functionData.FunctionDefinition.Parameters[i].DefaultValue.Value; } scopeVariables.Add(variableName, new TypedValue(variableType, variableValue)); } // start executing the function context if (functionData.Context is SyneryParser.BlockContext) { /* 1. Create scope for the function block with the given parameters set as variables. * Set the global scope as parent to avoid accessing variables of this scope. * 2. Execute the function block. * 3. Get the return value from the function block. */ IFunctionScope functionScope = new FunctionScope(controller.Memory.GlobalScope, functionData, scopeVariables); controller.Interpret <SyneryParser.BlockContext, INestedScope, INestedScope>((SyneryParser.BlockContext)functionData.Context, functionScope); returnValue = functionScope.ReturnValue; } else { throw new SyneryInterpretationException(functionData.Context, "Unknown function content cannot be interpreted."); } // validate the return value if (functionData.FunctionDefinition.HasReturnValue == true && returnValue == null) { string message = String.Format( "Function has no return value but is expected to return '{0}'. Function called on line: '{1}'.", functionData.FunctionDefinition.ReturnType.PublicName, functionCallContext.Start.Line); throw new SyneryInterpretationException(functionData.Context, message); } else if (functionData.FunctionDefinition.HasReturnValue == true && functionData.FunctionDefinition.ReturnType != returnValue.Type) { string message = String.Format( "Function has wrong return value. Expected: '{0}' / Given: '{1}'. Function called on line: '{2}'.", functionData.FunctionDefinition.ReturnType.PublicName, returnValue.Type.PublicName, functionCallContext.Start.Line); throw new SyneryInterpretationException(functionData.Context, message); } return(returnValue); }
/// <summary> /// Creates a new space in memory for a variable with the given name and type. /// </summary> /// <param name="name"></param> /// <param name="type"></param> public void DeclareVariable(string name, SyneryType type) { _Variables[name] = new TypedValue(type); }
public IValue RunWithResult(SyneryParser.LiteralContext context) { SyneryType type = null; object literalValue = null; if (context.StringLiteral() != null) { type = TypeHelper.STRING_TYPE; literalValue = LiteralHelper.ParseStringLiteral(context.StringLiteral()); } else if (context.VerbatimStringLiteral() != null) { type = TypeHelper.STRING_TYPE; literalValue = LiteralHelper.ParseVerbatimStringLiteral(context.VerbatimStringLiteral()); } else if (context.IntegerLiteral() != null) { type = TypeHelper.INT_TYPE; literalValue = Convert.ChangeType(context.GetText(), typeof(int)); } else if (context.DoubleLiteral() != null) { type = TypeHelper.DOUBLE_TYPE; literalValue = Convert.ToDouble(context.GetText(), new NumberFormatInfo() { NumberDecimalSeparator = "." }); } else if (context.DecimalLiteral() != null) { type = TypeHelper.DECIMAL_TYPE; string decimalValue = context.GetText().TrimEnd(new char[] { 'M', 'm' }); literalValue = Convert.ToDecimal(decimalValue, new NumberFormatInfo() { NumberDecimalSeparator = "." }); } else if (context.CharLiteral() != null) { type = TypeHelper.CHAR_TYPE; char[] chars = context.GetText().ToCharArray(1, 1); if (chars.Length == 1) { literalValue = Convert.ToChar(chars[0]); } else { throw new SyneryInterpretationException(context, String.Format("The value '{0}' is not a valid char literal.", context.GetText())); } } else if (context.BooleanLiteral() != null) { type = TypeHelper.BOOL_TYPE; if (context.BooleanLiteral().GetText() == "TRUE") { literalValue = true; } else if (context.BooleanLiteral().GetText() == "FALSE") { literalValue = false; } else { throw new SyneryInterpretationException(context, String.Format("The value '{0}' is not a valid boolean literal.", context.GetText())); } } else if (context.dateTimeLiteral() != null) { type = TypeHelper.DATETIME_TYPE; literalValue = Controller.Interpret <SyneryParser.DateTimeLiteralContext, DateTime>(context.dateTimeLiteral()); } else if (context.NullLiteral() != null) { type = null; literalValue = null; } else { throw new SyneryInterpretationException(context, String.Format("Unknown Literal type in {0} for the value '{0}'.", this.GetType().Name, context.GetText())); } return(new TypedValue(type, literalValue)); }
private void ExtractRecordTypes(string code, IDictionary <string, string> includeCode = null) { int endlessLoopPreventionCounter = 0; IList <RecordTypeDelcarationContainer> listOfDeclrartionContainer = GetRecordTypeContexts(code, includeCode); // assure that there is a dictionary if (Memory.RecordTypes == null) { Memory.RecordTypes = new Dictionary <SyneryType, IRecordType>(); } // extract all RecordTypes without a base type var listOfDeclarationsWithoutBaseType = (from d in listOfDeclrartionContainer where d.BaseRecordFullName == null select d).ToList(); foreach (var item in listOfDeclarationsWithoutBaseType) { IRecordType recordType = Controller .Interpret <SyneryParser.RecordTypeDeclarationContext, IRecordType, RecordTypeDelcarationContainer>(item.RecordTypeDeclarationContext, item); SyneryType syneryType = new SyneryType(typeof(IRecord), recordType.FullName); // set the alias of the included code file if (item.CodeFileAlias != null) { recordType.CodeFileAlias = item.CodeFileAlias; } Memory.RecordTypes.Add(syneryType, recordType); listOfDeclrartionContainer.Remove(item); } // loop threw the list of RecordTypes with a base type // assure that a RecordType only is loaded if the base type already is available while (listOfDeclrartionContainer.Count != 0) { var listOfAvailableTypes = Memory.RecordTypes.Select(r => r.Value.FullName); var listOfDeclarationsWithAvailableBaseTypes = (from d in listOfDeclrartionContainer where listOfAvailableTypes.Contains(d.BaseRecordFullName) select d).ToList(); // extract all RecordTypes for which the base type already is available foreach (var item in listOfDeclarationsWithAvailableBaseTypes) { IRecordType recordType = Controller .Interpret <SyneryParser.RecordTypeDeclarationContext, IRecordType, RecordTypeDelcarationContainer>(item.RecordTypeDeclarationContext, item); SyneryType syneryType = new SyneryType(typeof(IRecord), recordType.FullName); // set the alias of the included code file if (item.CodeFileAlias != null) { recordType.CodeFileAlias = item.CodeFileAlias; } Memory.RecordTypes.Add(syneryType, recordType); listOfDeclrartionContainer.Remove(item); } // prevent an endless loop: // if the counter reaches the 1000-mark the loop is stopped by throwing an exception endlessLoopPreventionCounter++; if (endlessLoopPreventionCounter > 1000) { // throw an exception that contains the name(s) of the left declarations that couldn't be resolved throw new SyneryException(String.Format( "The base type for the following record types couldn't be resolved: {0}", String.Join(", ", listOfDeclrartionContainer.Select(d => String.Format("'{0} : {1}'", d.FullName, d.BaseRecordFullName))))); } } }
private static KeyValuePair <SyneryType, IRecordType> GetRecordTypeSignature(IRecordType recordType) { SyneryType syneryType = new SyneryType(typeof(IRecord), recordType.Name); return(new KeyValuePair <SyneryType, IRecordType>(syneryType, recordType)); }
public static IValue GetDefaultValue(SyneryType type) { return(GetDefaultValue(type.UnterlyingDotNetType)); }