Beispiel #1
0
        public static LNode useSymbols(LNode input, IMacroContext context)
        {
            bool inType = context.Ancestors.Any(parent => {
                var kind = EcsValidators.SpaceDefinitionKind(parent);
                return(kind != null && kind != S.Namespace);
            });
            var args_body = context.GetArgsAndBody(true);

            return(UseSymbolsCore(input.Attrs, args_body.A, args_body.B, context, inType));
        }
Beispiel #2
0
 public static LNode Constructor(LNode cons, IMacroContext context)
 {
     if (cons.ArgCount >= 3 && cons.Args[1].IsIdNamed(S.This))
     {
         var    anc = context.Ancestors;
         LNode  space = anc.TryGet(anc.Count - 3, LNode.Missing), typeName;
         Symbol type = EcsValidators.SpaceDefinitionKind(space);
         if (type != null && anc[anc.Count - 2] == space.Args[2])
         {
             typeName = space.Args[0];
             return(cons.WithArgChanged(1, F.Id(KeyNameComponentOf(typeName))));
         }
     }
     return(null);
 }
Beispiel #3
0
        private static LNode CompileTimeMacro(string macroName, LNode node, IMacroContext context, bool alsoRuntime, bool wantPreprocess = true)
        {
            if (node.ArgCount != 1 || !node[0].Calls(S.Braces))
            {
                context.Error(node.Target, "{0} should have a single argument: a braced block.", macroName);
                return(null);
            }

            LNodeList code = node[0].Args;

            if (wantPreprocess)
            {
                if (context.Ancestors.Take(context.Ancestors.Count - 1).Any(
                        n => n.Name.IsOneOf(S.Class, S.Struct, S.Enum, S.Namespace) ||
                        n.Name.IsOneOf(S.Constructor, S.Fn, S.Property, S.Var)))
                {
                    context.Error(node.Target, "{0} is designed for use only at the top level of the file. It will be executed as though it is at the top level: any outer scopes will be ignored.", macroName);
                }

                code = context.PreProcess(code);
            }

            WriteHeaderCommentInSessionLog(node, context.Sink);

            // Remove namespace blocks (not supported by Roslyn scripting)
            LNode namespaceBlock     = null;
            var   codeSansNamespaces = code.RecursiveReplace(RemoveNamespaces);

            LNodeList?RemoveNamespaces(LNode n)
            {
                if (EcsValidators.SpaceDefinitionKind(n, out _, out _, out LNode body) == S.Namespace)
                {
                    namespaceBlock = n;
                    return(body.Args.RecursiveReplace(RemoveNamespaces));
                }
                return(null);
            }

            if (namespaceBlock != null && wantPreprocess)
            {
                context.Warning(namespaceBlock, "The C# scripting engine does not support namespaces. They will be ignored when running at compile time.");
            }

            RunCSharpCodeWithRoslyn(node, codeSansNamespaces, context);

            _roslynSessionLog?.Flush();
            return(alsoRuntime ? F.Splice(code) : F.Splice());
        }
Beispiel #4
0
 public static LNode DetectCurrentNamespace(LNode node, IMacroContext context)
 {
     if (EcsValidators.SpaceDefinitionKind(context.Parent, out LNode name, out _, out _) == S.Namespace)
     {
         var newNamespace     = name.Print(ParsingMode.Expressions);
         var currentNamespace = context.ScopedProperties.TryGetValue(_currentNamespace, null) as Symbol;
         if (currentNamespace == null)
         {
             currentNamespace = (Symbol)newNamespace;
         }
         else
         {
             currentNamespace = (Symbol)(currentNamespace.Name + "." + newNamespace);
         }
         context.OpenMacroNamespaces.Add(currentNamespace);
         context.ScopedProperties[_currentNamespace] = currentNamespace;
     }
     return(null);            // don't alter output
 }
Beispiel #5
0
            public LNode EliminateBlockExprs(LNode stmt, bool isDeclContext)
            {
                LNode retType, name, argList, bases, body, initValue;

                if (EcsValidators.SpaceDefinitionKind(stmt, out name, out bases, out body) != null)
                {
                    return(body == null ? stmt : stmt.WithArgChanged(2, EliminateBlockExprs(body, true)));
                }
                else if (EcsValidators.MethodDefinitionKind(stmt, out retType, out name, out argList, out body, true) != null)
                {
                    return(body == null ? stmt : stmt.WithArgChanged(3, EliminateBlockExprs(body, false)));
                }
                else if (EcsValidators.IsPropertyDefinition(stmt, out retType, out name, out argList, out body, out initValue))
                {
                    stmt = stmt.WithArgChanged(3, EliminateBlockExprs(body, false));
                    if (initValue != null)
                    {
                        var initMethod = EliminateRunSeqFromInitializer(retType, name, ref initValue);
                        if (initMethod != null)
                        {
                            stmt = stmt.WithArgChanged(4, initValue);
                            return(LNode.Call(CodeSymbols.Splice, LNode.List(stmt, initMethod)));
                        }
                    }
                    return(stmt);
                }
                else if (!isDeclContext)
                {
                    return(EliminateBlockExprsInExecStmt(stmt));
                }
                else if (stmt.CallsMin(S.Var, 2))
                {
                    var results = new List <LNode> {
                        stmt
                    };
                    var vars    = stmt.Args;
                    var varType = vars[0];
                    for (int i = 1; i < vars.Count; i++)
                    {
                        {
                            var tmp_1 = vars[i];
                            if (tmp_1.Calls(CodeSymbols.Assign, 2) && (name = tmp_1.Args[0]) != null && (initValue = tmp_1.Args[1]) != null)
                            {
                                var initMethod = EliminateRunSeqFromInitializer(varType, name, ref initValue);
                                if (initMethod != null)
                                {
                                    results.Add(initMethod);
                                    vars[i] = vars[i].WithArgChanged(1, initValue);
                                }
                            }
                        }
                    }
                    if (results.Count > 1)
                    {
                        results[0] = stmt.WithArgs(vars);
                        return(LNode.List(results).AsLNode(S.Splice));
                    }
                    return(stmt);
                }
                else
                {
                    return(stmt);
                }
            }
Beispiel #6
0
        public static LNodeList UseSymbolsCore(LNodeList symbolAttrs, LNodeList options, LNodeList body, IMacroContext context, bool inType)
        {
            // Decode options (TODO: invent a simpler approach)
            string prefix    = "sy_";
            var    inherited = new HashSet <Symbol>();

            foreach (var pair in MacroContext.GetOptions(options))
            {
                if (pair.Key.Name.Name == "prefix" && pair.Value.IsId)
                {
                    prefix = pair.Value.Name.Name;
                }
                else if (pair.Key.Name.Name == "inherit" && pair.Value.Value is Symbol)
                {
                    inherited.Add((Symbol)pair.Value.Value);
                }
                else if (pair.Key.Name.Name == "inherit" && (pair.Value.Calls(S.Braces) || pair.Value.Calls(S.Tuple)) && pair.Value.Args.All(n => n.Value is Symbol))
                {
                    foreach (var arg in pair.Value.Args)
                    {
                        inherited.Add((Symbol)arg.Value);
                    }
                }
                else
                {
                    context.Sink.Warning(pair.Key, "Unrecognized parameter. Expected prefix:id or inherit:{@@A; @@B; ...})");
                }
            }

            // Replace all symbols while collecting a list of them
            var       symbols = new Dictionary <Symbol, LNode>();
            LNodeList output  = body.SmartSelect(stmt =>
                                                 stmt.ReplaceRecursive(n => {
                if (!inType && n.ArgCount == 3)
                {
                    // Since we're outside any type, we must avoid creating symbol
                    // fields. When we cross into a type then we can start making
                    // Symbols by calling ourself recursively with inType=true
                    var kind = EcsValidators.SpaceDefinitionKind(n);
                    if (kind == S.Class || kind == S.Struct || kind == S.Interface || kind == S.Alias || kind == S.Trait)
                    {
                        var body2 = n.Args[2];
                        return(n.WithArgChanged(2, body2.WithArgs(UseSymbolsCore(symbolAttrs, options, body2.Args, context, true))));
                    }
                }
                var sym = n.Value as Symbol;
                if (n.IsLiteral && sym != null)
                {
                    return(symbols[sym] = LNode.Id(prefix + sym.Name));
                }
                return(null);
            })
                                                 );

            // Return updated code with variable declaration at the top for all non-inherit symbols used.
            var _Symbol = F.Id("Symbol");
            var vars    = (from sym in symbols
                           where !inherited.Contains(sym.Key)
                           select F.Call(S.Assign, sym.Value,
                                         F.Call(S.Cast, F.Literal(sym.Key.Name), _Symbol))).ToList();

            if (vars.Count > 0)
            {
                output.Insert(0, F.Call(S.Var, ListExt.Single(_Symbol).Concat(vars))
                              .WithAttrs(symbolAttrs.Add(F.Id(S.Static)).Add(F.Id(S.Readonly))));
            }
            return(output);
        }
            public LNode EliminateSequenceExpressions(LNode stmt, bool isDeclContext)
            {
                LNode retType, name, argList, bases, body, initValue;

                if (EcsValidators.SpaceDefinitionKind(stmt, out name, out bases, out body) != null)
                {
                    // Space definition: class, struct, etc.
                    return(body == null ? stmt : stmt.WithArgChanged(2, EliminateSequenceExpressions(body, true)));
                }
                else if (EcsValidators.MethodDefinitionKind(stmt, out retType, out name, out argList, out body, true) != null)
                {
                    // Method definition
                    return(body == null ? stmt : stmt.WithArgChanged(3, EliminateSequenceExpressionsInLambdaExpr(body, retType)));
                }
                else if (EcsValidators.IsPropertyDefinition(stmt, out retType, out name, out argList, out body, out initValue))
                {
                    // Property definition
                    stmt = stmt.WithArgChanged(3,
                                               body.WithArgs(part => {
                        if (part.ArgCount == 1 && part[0].Calls(S.Braces))
                        {
                            part = part.WithArgChanged(0, EliminateSequenceExpressions(part[0], false));
                        }
                        return(part);
                    }));
                    if (initValue != null)
                    {
                        var initMethod = EliminateRunSeqFromInitializer(retType, name, ref initValue);
                        if (initMethod != null)
                        {
                            stmt = stmt.WithArgChanged(4, initValue);
                            return(LNode.Call((Symbol)"#runSequence", LNode.List(stmt, initMethod)));
                        }
                    }
                    return(stmt);
                }
                else if (stmt.Calls(CodeSymbols.Braces))
                {
                    return(stmt.WithArgs(EliminateSequenceExpressions(stmt.Args, isDeclContext)));
                }
                else if (!isDeclContext)
                {
                    return(EliminateSequenceExpressionsInExecStmt(stmt));
                }
                else if (stmt.CallsMin(S.Var, 2))
                {
                    // Eliminate blocks from field member
                    var results = new List <LNode> {
                        stmt
                    };
                    var vars    = stmt.Args;
                    var varType = vars[0];
                    for (int i = 1; i < vars.Count; i++)
                    {
                        var @var = vars[i];
                        if (@var.Calls(CodeSymbols.Assign, 2) && (name = @var.Args[0]) != null && (initValue = @var.Args[1]) != null)
                        {
                            var initMethod = EliminateRunSeqFromInitializer(varType, name, ref initValue);
                            if (initMethod != null)
                            {
                                results.Add(initMethod);
                                vars[i] = vars[i].WithArgChanged(1, initValue);
                            }
                        }
                    }
                    if (results.Count > 1)
                    {
                        results[0] = stmt.WithArgs(vars);
                        return(LNode.List(results).AsLNode(__numrunSequence));
                    }
                    return(stmt);
                }
                else
                {
                    return(stmt);
                }
            }