internal static dynamic Switch(object rawTest, List <SwitchCase> cases, object rawDefaultBlock, object rawScope) { var test = (Expression)rawTest; var defaultBlock = rawDefaultBlock != null ? (Expression)rawDefaultBlock : NovaExpression.NovaBlock(NovaExpression.Default(cases.First().Body.Type)); var scope = (NovaScope)rawScope; dynamic retVal = null; var found = false; var tval = CompilerServices.CompileExpression(test, scope); foreach (var @case in cases.Where(@case => @case.TestValues.Select(testValue => CompilerServices.CompileExpression(testValue, scope)) .Any(xval => Binary(tval, xval, E.Equal, scope)))) { found = true; retVal = CompilerServices.CompileExpression(@case.Body, scope); } if (!found) { retVal = CompilerServices.CompileExpression(defaultBlock, scope); } return(retVal); }
private static dynamic InstanceEval(object self, string eval, NovaScope scope) { if (!(self is NovaInstance instance)) { return(null); } var xexpression = string.Format("{0};", eval); var res = NovaParser.Parse(xexpression); Expression block; if (res != null) { scope["self"] = scope["super"] = instance; scope["<nova_context_invokemember>"] = true; string selfName; var selfScope = scope.SearchForObject(instance, out selfName); if (selfScope != null && selfName != null) { scope["<nova_context_selfscope>"] = selfScope; scope["<nova_context_selfname>"] = selfName; } block = NovaExpression.NovaBlock(res); // We want eval'd expressions to execute in the current scope, not its own child scopes. This ensures assignment evals work properly. ((BlockExpression)block).Scope = scope; ((BlockExpression)block).SetChildrenScopes(scope); } else { return(null); } var val = CompilerServices.CreateLambdaForExpression(block)(); return(val); }
public static BlockExpression GenerateBody(Type type, MethodBase method) { var body = new List <Expression>(); body.Add( NovaExpression.Invoke( Expression.Constant(method.IsConstructor ? typeof(NovaInstance) : type, typeof(Type)), Expression.Constant(method, typeof(MethodBase)), ArgumentCache[method])); body.Add(Expression.Label(NovaParser.ReturnTarget, Expression.Constant(null, typeof(object)))); return(NovaExpression.NovaBlock(body.ToArray())); }
public override ScriptCode CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink) { var res = NovaParser.Parse(sourceUnit.GetCode(), sourceUnit); if (res != null) { Expression mainBlock = NovaExpression.NovaBlock(res); return(new NovaScriptCode(mainBlock, sourceUnit)); } else { throw new SyntaxErrorException("Syntax error", sourceUnit, SourceSpan.None, 0, Severity.Error); } }
private static dynamic Eval(string eval, NovaScope scope) { var xexpression = string.Format("{0};", eval); var res = NovaParser.Parse(xexpression); Expression block; if (res != null) { block = NovaExpression.NovaBlock(res); // We want eval'd expressions to execute in the current scope, not its own child scopes. This ensures assignment evals work properly. ((BlockExpression)block).Scope = scope; ((BlockExpression)block).SetChildrenScopes(scope); } else { return(null); } var val = CompilerServices.CreateLambdaForExpression(block)(); return(val); }
public NovaClass(string name, NovaClass parent, List <NovaFunction> classMethods, List <NovaFunction> instanceMethods) { Name = name; ClassMethods = new Dictionary <string, NovaMethodTable>(); classMethods.ForEach(func => AddMethod(ClassMethods, func)); if (!ClassMethods.ContainsKey("new")) { AddMethod(ClassMethods, new NovaFunction("new", new List <FunctionArgument>(), NovaExpression.NovaBlock( NovaExpression.Return(new List <FunctionArgument> { new FunctionArgument(null, NovaExpression.Variable(Expression.Constant("self"))) }), Expression.Label(NovaParser.ReturnTarget, Expression.Constant(null, typeof(object)))), new NovaScope())); } InstanceMethods = new Dictionary <string, NovaMethodTable>(); instanceMethods.ForEach(func => AddMethod(InstanceMethods, func)); UndefinedMethods = new List <string>(); RemovedMethods = new List <string>(); Context = new NovaScope(); Parent = parent; }
internal static dynamic DefineClass(object rawName, object rawParent, List <Expression> contents, object rawScope) { lock (_classDefineLock) { if (Resolve(rawName, rawScope) != null) { return(DefineCategory(Resolve(rawName, rawScope), contents, rawScope)); } var scope = (NovaScope)rawScope; var defineScope = _inClassDefine ? scope : scope.GlobalScope; _inClassDefine = true; NovaClass parent; if (rawParent == null) { if (scope.GlobalScope["Object"] == null) { scope.GlobalScope["Object"] = Nova.Box(typeof(object)); } parent = scope.GlobalScope["Object"]; } else { var dParent = Resolve(rawParent as string, scope); if (dParent == null) { _inClassDefine = false; return(null); } if (dParent is Type) { parent = Nova.Box(dParent); } else { parent = dParent as NovaClass; } if (parent == null) { _inClassDefine = false; return(null); } } var name = (string)rawName; _className = name; var @class = new NovaClass { Name = _className, Parent = parent }; var xScope = new NovaScope(scope); xScope["self"] = @class; xScope[_className] = @class; _currentClassScope = xScope; contents.ForEach(content => { if (content is IncludeExpression) { // We only include modules here so make sure this include references a module var names = ((IncludeExpression)content).Names; dynamic module = null; var index = 0; names.ForEach(mname => { if ((module is NovaModule)) { module = module.Context[mname]; } else if (index == 0) { module = scope[mname]; } index = index + 1; }); if (module != null) { if (module is NovaModule) { ((NovaModule)module).Contents.ForEach(mcon => { if (mcon is NovaFunction) { if ((mcon as NovaFunction).IsSingleton || (mcon as NovaFunction).Name == "new") { NovaClass.AddMethod(@class.ClassMethods, mcon as NovaFunction); } else { NovaClass.AddMethod(@class.InstanceMethods, mcon as NovaFunction); } if (@class.RemovedMethods.Contains((mcon as NovaFunction).Name)) { @class.RemovedMethods.Remove((mcon as NovaFunction).Name); } if (@class.UndefinedMethods.Contains((mcon as NovaFunction).Name)) { @class.UndefinedMethods.Remove((mcon as NovaFunction).Name); } } }); xScope.MergeWithScope(module.Context); } else if (module is NovaClass) { xScope[((NovaClass)module).Name] = module; } } } }); contents.ForEach(content => { if (!(content is IncludeExpression)) { var result = CompilerServices.CompileExpression(content, xScope); if (result is NovaFunction) { if ((result as NovaFunction).IsSingleton || (result as NovaFunction).Name == "new") { NovaClass.AddMethod(@class.ClassMethods, result as NovaFunction); } else { NovaClass.AddMethod(@class.InstanceMethods, result as NovaFunction); } if (@class.RemovedMethods.Contains((result as NovaFunction).Name)) { @class.RemovedMethods.Remove((result as NovaFunction).Name); } if (@class.UndefinedMethods.Contains((result as NovaFunction).Name)) { @class.UndefinedMethods.Remove((result as NovaFunction).Name); } } } }); if ([email protected]("new")) { NovaClass.AddMethod(@class.ClassMethods, new NovaFunction("new", new List <FunctionArgument>(), NovaExpression.NovaBlock( NovaExpression.Return(new List <FunctionArgument> { new FunctionArgument(null, NovaExpression.Variable(Expression.Constant("self"))) }), Expression.Label(NovaParser.ReturnTarget, Expression.Constant(null, typeof(object)))), new NovaScope())); } @class.Context = xScope; defineScope[@class.Name] = @class; _inClassDefine = false; return(@class); } }
public Expression Compile(string rawsource) { var res = NovaParser.Parse(rawsource); return(res != null?NovaExpression.NovaBlock(res) : null); }
internal static dynamic String(object rawEval, object rawScope) { StringBuilder @new; var eval = rawEval as String; var components = eval.Split(new[] { "#{" }, StringSplitOptions.None); if (components.Count() == 1) { return(new NovaString(eval)); } @new = new StringBuilder(components[0]); for (var i = 1; i < components.Count(); i++) { var parts = components[i].Split(new[] { "}" }, StringSplitOptions.None); var expression = parts[0]; var escapeString = false; if (expression != null && expression[0] == ':') { escapeString = true; expression = expression.Substring(1); } if (expression != null) { var scope = (NovaScope)rawScope; var xexpression = string.Format("{0};", expression); var res = NovaParser.Parse(xexpression); Expression block; if (res != null) { block = NovaExpression.NovaBlock(res); } else { return(null); } var myScope = new NovaScope(); var visitor = new VariableNameVisitor(); visitor.Visit(block); visitor.VariableNames.ForEach(name => myScope[name] = scope[name]); var val = CompilerServices.CompileExpression(block, myScope); if (val != null) { string stringVal = val.ToString(); if (escapeString && val is string) { stringVal = string.Format("\"{0}\"", stringVal); } @new.Append(stringVal ?? ""); } else { @new.Append(expression); } } if (parts.Count() > 1) { @new.Append(parts[1]); var j = 2; while (j < parts.Count()) { @new.Append("}"); @new.Append(parts[j++]); } } } return(new NovaString(@new.ToString())); }