示例#1
0
        public void ResolveCodeOrState(StatesInfo statesInfo)
        {
            if (codeOrStateResolved)
            {
                return;
            }

            string code_str = code.AsString().Trim().Replace(" ", "");

            if (PopState == code_str)
            {
                targetState = PopState;
                code        = null;
            }
            else
            {
                string state = statesInfo.StateNames.SingleOrDefault(it => pushState + it == code_str);
                if (state != null)
                {
                    targetState = state;
                    code        = null;
                }
            }

            codeOrStateResolved = true;
        }
示例#2
0
        public CodeBody TryParseBodyOrStatement(bool allowEmpty = false)
        {
            Func <ASTNode> bodyParser = () =>
            {
                CodeBody body   = null;
                var      single = TryParseInnerStatement();
                if (single != null)
                {
                    var content = new List <Statement>();
                    content.Add(single);
                    body = new CodeBody(content, single.StartPos, single.EndPos);
                }
                else
                {
                    body = TryParseBody();
                }
                if (body == null)
                {
                    if (allowEmpty && Tokens.ConsumeToken(TokenType.SemiColon) != null)
                    {
                        body = new CodeBody(null, CurrentPosition.GetModifiedPosition(0, -1, -1), CurrentPosition);
                    }
                    else
                    {
                        return(Error("Expected a code body or single statement!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }
                }

                return(body);
            };

            return((CodeBody)Tokens.TryGetTree(bodyParser));
        }
 public bool VisitNode(CodeBody node)
 {
     foreach (Statement statement in node.Statements)
     {
         Emit(statement);
     }
     return(true);
 }
示例#4
0
 public FactoryTypeInfo(string name, string parent, bool withOverride)
 {
     this.ClassName    = name;
     this.Parent       = parent;
     this.WithOverride = withOverride;
     this.Code         = new CodeBody();
     this.Params       = new CodeBody();
 }
示例#5
0
        public bool VisitNode(CodeBody node)
        {
            foreach (Statement s in node.Statements) //TODO: make this proper
            {
                s.AcceptVisitor(this);
            }

            return(true);
        }
示例#6
0
        private static AltRule createSubstitution(SymbolPosition position, string substSymbolName)
        {
            var code = new CodeBody().AddIdentifier("obj");

            return(AltRule.CreateInternally(position, new RhsGroup[] {
                RhsGroup.CreateSequence(position, RepetitionEnum.Once, new RhsSymbol(position, "obj", substSymbolName))
            },
                                            new CodeMix(CodeMix.SubstitutionComment).AddBody(code)));
        }
示例#7
0
 /// <summary>
 /// Debugging routine to dump the code to a given file. Can be called directly from within
 /// the debugger.
 /// </summary>
 /// <param name="output"></param>
 internal void DumpToFile(System.IO.FileInfo output)
 {
     using (var writer = output.CreateText())
     {
         foreach (var l in CodeBody.CodeItUp())
         {
             writer.WriteLine(l);
         }
     }
 }
示例#8
0
        public bool VisitNode(CodeBody node)
        {
            foreach (Statement s in node.Statements) //TODO: make this proper
            {
                if (s.AcceptVisitor(this) && !StringParserBase.SemiColonExceptions.Contains(s.Type))
                {
                    Append(";");
                }
            }

            return(true);
        }
示例#9
0
        private LexItem(IEnumerable <ILexPattern> patterns, IEnumerable <string> contextTokens, string token, string state, bool isExpression, CodeBody code, bool resolved)
        {
            this.states        = new HashSet <string>();
            this.InputPatterns = patterns.ToArray();
            this.Context       = contextTokens.ToArray();
            this.TerminalName  = token;
            this.targetState   = state;
            this.code          = code;
            this.IsExpression  = isExpression;

            this.codeOrStateResolved = (resolved || this.targetState != null || this.code == null);
        }
示例#10
0
        public IfStatement TryParseIf()
        {
            Func <ASTNode> ifParser = () =>
            {
                var token = Tokens.ConsumeToken(TokenType.If);
                if (token == null)
                {
                    return(null);
                }

                if (Tokens.ConsumeToken(TokenType.LeftParenth) == null)
                {
                    return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var condition = TryParseExpression();
                if (condition == null)
                {
                    return(Error("Expected an expression as the if-condition!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }
                if (condition.ResolveType().Name != "bool") // TODO: check/fix!
                {
                    return(Error("Expected a boolean result from the condition!", condition.StartPos, condition.EndPos));
                }

                if (Tokens.ConsumeToken(TokenType.RightParenth) == null)
                {
                    return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                CodeBody thenBody = TryParseBodyOrStatement();
                if (thenBody == null)
                {
                    return(Error("Expected a statement or code block!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                CodeBody elseBody  = null;
                var      elsetoken = Tokens.ConsumeToken(TokenType.Else);
                if (elsetoken != null)
                {
                    elseBody = TryParseBodyOrStatement();
                    if (elseBody == null)
                    {
                        return(Error("Expected a statement or code block!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }
                }

                return(new IfStatement(condition, thenBody, token.StartPosition, token.EndPosition, elseBody));
            };

            return((IfStatement)Tokens.TryGetTree(ifParser));
        }
示例#11
0
        public DoUntilLoop TryParseDoUntil()
        {
            Func <ASTNode> untilParser = () =>
            {
                var doToken = Tokens.ConsumeToken(TokenType.Do);
                if (doToken == null)
                {
                    return(null);
                }

                _loopCount++;
                CodeBody body = TryParseBodyOrStatement();
                _loopCount--;
                if (body == null)
                {
                    return(null);
                }

                var untilToken = Tokens.ConsumeToken(TokenType.Until);
                if (untilToken == null)
                {
                    return(Error("Expected 'until'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                if (Tokens.ConsumeToken(TokenType.LeftParenth) == null)
                {
                    return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var condition = TryParseExpression();
                if (condition == null)
                {
                    return(Error("Expected an expression as the until condition!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }
                if (condition.ResolveType().Name != "bool") // TODO: check/fix!
                {
                    return(Error("Expected a boolean result from the condition!", condition.StartPos, condition.EndPos));
                }

                if (Tokens.ConsumeToken(TokenType.RightParenth) == null)
                {
                    return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                return(new DoUntilLoop(condition, body, untilToken.StartPosition, untilToken.EndPosition));
            };

            return((DoUntilLoop)Tokens.TryGetTree(untilParser));
        }
示例#12
0
        private static AltRule createAppend(SymbolPosition position,
                                            string lhsSymbolName,
                                            IEnumerable <string> elementTypeNames,
                                            params RhsSymbol[] symbols)
        {
            // if it does not exists it means we don't care about adding it
            IEnumerable <RhsSymbol> named_symbols = symbols.Where(it => it.ObjName != null).ToArray();

            string list_obj_name;

            if (named_symbols.Count() == 1)
            {
                list_obj_name = "list";
            }
            else
            {
                list_obj_name = "tuple_list";
            }

            // since we are creating this code, the only conflict can come from symbol object names
            list_obj_name = Grammar.RegisterName(list_obj_name, named_symbols.Select(it => it.ObjName).ToList());

            var code = new CodeBody().AddSnippet("{");

            if (named_symbols.Count() == 1)
            {
                code.AddWithIdentifier(list_obj_name, ".", "Add", "(", named_symbols.Single().ObjName, ");");
            }
            else
            {
                foreach (Tuple <RhsSymbol, int> sym_pair in named_symbols.ZipWithIndex())
                {
                    code.AddWithIdentifier(list_obj_name, ".", CodeWords.Item(sym_pair.Item2 + 1), ".", "Add", "(");
                    code.AddIdentifier(sym_pair.Item1.ObjName);
                    code.AddSnippet(");");
                }
            }

            code.AddWithIdentifier("return", " ", list_obj_name, ";}");

            return(AltRule.CreateInternally(position, new RhsGroup[] {
                RhsGroup.CreateSequence(position, RepetitionEnum.Once, new RhsSymbol(position, list_obj_name, lhsSymbolName)),
                RhsGroup.CreateSequence(position, RepetitionEnum.Once, symbols.Select(it => it.ShallowClone().SetSkip(false)).ToArray())
            },
                                            new CodeMix(CodeMix.AppendComment).AddBody(code)));
        }
示例#13
0
        public WhileLoop TryParseWhile()
        {
            Func <ASTNode> whileParser = () =>
            {
                var token = Tokens.ConsumeToken(TokenType.While);
                if (token == null)
                {
                    return(null);
                }

                if (Tokens.ConsumeToken(TokenType.LeftParenth) == null)
                {
                    return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var condition = TryParseExpression();
                if (condition == null)
                {
                    return(Error("Expected an expression as the while condition!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }
                if (condition.ResolveType().Name != "bool") // TODO: check/fix!
                {
                    return(Error("Expected a boolean result from the condition!", condition.StartPos, condition.EndPos));
                }

                if (Tokens.ConsumeToken(TokenType.RightParenth) == null)
                {
                    return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                _loopCount++;
                CodeBody body = TryParseBodyOrStatement(allowEmpty: true);
                _loopCount--;
                if (body == null)
                {
                    return(null);
                }

                return(new WhileLoop(condition, body, token.StartPosition, token.EndPosition));
            };

            return((WhileLoop)Tokens.TryGetTree(whileParser));
        }
示例#14
0
        private static CodeBody makeTupleListCode(IEnumerable <string> elementTypeNames)
        {
            if (!elementTypeNames.Any())
            {
                throw new ArgumentException();
            }

            if (elementTypeNames.Count() == 1)
            {
                return(makeListCode(elementTypeNames.Single()));
            }
            else
            {
                var code = new CodeBody()
                           .AddWithIdentifier(CodeWords.Tuple, "<")
                           .AddCommaSeparatedElements(elementTypeNames.Select(it => makeListCode(it)))
                           .AddSnippet(">");

                return(code);
            }
        }
示例#15
0
        public SwitchStatement TryParseSwitch()
        {
            Func <ASTNode> switchParser = () =>
            {
                var token = Tokens.ConsumeToken(TokenType.Switch);
                if (token == null)
                {
                    return(null);
                }

                if (Tokens.ConsumeToken(TokenType.LeftParenth) == null)
                {
                    return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var expression = TryParseExpression();
                if (expression == null)
                {
                    return(Error("Expected an expression as the switch value!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                if (Tokens.ConsumeToken(TokenType.RightParenth) == null)
                {
                    return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                _switchCount++;
                CodeBody body = TryParseBodyOrStatement();
                _switchCount--;
                if (body == null)
                {
                    return(Error("Expected switch code block!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                return(new SwitchStatement(expression, body, token.StartPosition, token.EndPosition));
            };

            return((SwitchStatement)Tokens.TryGetTree(switchParser));
        }
示例#16
0
        // funcRef == null, means it is (not created because it is pointless) identity function
        private CodeBody createFunctionCall(CodeBody funcRef, IEnumerable <CodeBody> arguments)
        {
            if (funcRef == null && arguments.Count() != 1)
            {
                throw new ArgumentException("Identity function works only for single argument");
            }

            var code = new CodeBody();

            if (funcRef != null)
            {
                code.Append(funcRef).AddSnippet("(");
            }

            code.AddCommaSeparatedElements(arguments);

            if (funcRef != null)
            {
                code.AddSnippet(")");
            }

            return(code);
        }
示例#17
0
        private string registerLambda(string lhsSymbol,
                                      IEnumerable <string> inputTypeNames,
                                      string outputTypeName,
                                      // each pair holds real name (like "expr") and (as backup) dummy name, like "_2"
                                      IEnumerable <Tuple <string, string> > arguments,
                                      CodeBody body)
        {
            if (inputTypeNames.Count() != arguments.Count())
            {
                throw new ArgumentException("Creating a function -- types count vs. arguments count mismatch.");
            }

            CodeLambda lambda = null;

            // identity function, i.e. f(x) = x, we check only real name, if it was a dummy name, it would be
            if (arguments.Count() == 1)
            {
                if (arguments.Single().Item1 == body.Make().Trim())
                {
                    lambda = FunctionRegistry.IdentityFunction(lhsSymbol);
                }
                else if (arguments.Single().Item2 == body.Make().Trim())
                {
                    throw new InvalidOperationException("Somehow dummy name which should not exist was referenced.");
                }
            }

            if (lambda == null)
            {
                lambda = new CodeLambda(lhsSymbol, arguments.SyncZip(inputTypeNames)
                                        .Select(it => FuncParameter.Create(it.Item1.Item1, it.Item1.Item2, it.Item2)),
                                        outputTypeName,
                                        body);
            }

            return(functionsRegistry.Add(lambda));
        }
示例#18
0
 public CodeBodyParser(TokenStream <String> tokens, CodeBody body, SymbolTable symbols, ASTNode containingNode, MessageLog log = null)
 {
     Log             = log ?? new MessageLog();
     Symbols         = symbols;
     Tokens          = tokens;
     _loopCount      = 0;
     _switchCount    = 0;
     Node            = containingNode;
     Body            = body;
     OuterClassScope = NodeUtils.GetOuterClassScope(containingNode);
     // TODO: refactor a better solution to this mess
     if (IsState)
     {
         NodeVariables = (containingNode as State);
     }
     else if (IsFunction)
     {
         NodeVariables = (containingNode as Function);
     }
     else if (IsOperator)
     {
         NodeVariables = (containingNode as OperatorDeclaration);
     }
 }
示例#19
0
 public bool VisitNode(CodeBody node)
 {
     throw new NotImplementedException();
 }
示例#20
0
        private void DecompileLoopsAndIfs(List <Statement> statements, Dictionary <Statement, ushort> positions, bool inLoop = false)
        {
            var defaultCaseStatements = new Stack <Statement>();
            var switchEnds            = new Dictionary <int, ushort>();

            for (int i = statements.Count - 1; i >= 0; i--)
            {
                var cur = statements[i];
                if (!positions.TryGetValue(cur, out ushort curPos))
                {
                    continue;                                                 //default param values, labels
                }
                if (cur is UnconditionalJump loopEnd && loopEnd.JumpLoc < curPos)
                {
                    //end of while or for loop
                    var       continueToPos            = curPos;
                    Statement statementBeforeEndOfLoop = statements[i - 1];
                    bool      isForLoop    = IsIncrementDecrement(statementBeforeEndOfLoop, out Statement update);
                    var       loopStart    = StatementLocations[loopEnd.JumpLoc];
                    int       conditionIdx = statements.IndexOf(loopStart);
                    int       skipStart    = conditionIdx;
                    int       numToSkip    = i - conditionIdx + 1;

                    if (!(statements[conditionIdx] is ConditionalJump conditionalJump))
                    {
                        //TODO: replace the unconditional jump with a goto? or perhaps this is a loop with no condition?
                        throw new Exception("Invalid Control Flow!");
                    }
                    CodeBody loopBody = new CodeBody(statements.GetRange(conditionIdx + 1, i - conditionIdx - 1));
                    if (!isForLoop && !(statementBeforeEndOfLoop is Jump))
                    {
                        //check to see if there is an unconditional jump to the statement before the end of the loop. This indicates a continue inside a for loop
                        var checkPos = positions[statementBeforeEndOfLoop];
                        if (loopBody.Statements.OfType <UnconditionalJump>().Any(possibleContinue => possibleContinue.JumpLoc == checkPos))
                        {
                            update    = statementBeforeEndOfLoop;
                            isForLoop = true;
                        }
                    }
                    else if (isForLoop)
                    {
                        //check to see if there is an unconditional jump to the end of the loop.
                        //This indicates that the loop is NOT a for loop, as there is no way to skip the increment statement in a for loop
                        for (int j = i - 2; j > conditionIdx; j--)
                        {
                            if (statements[j] is UnconditionalJump unj && unj.JumpLoc == curPos)
                            {
                                isForLoop = false;
                                break;
                            }
                        }
                    }
                    AssignStatement forInit = null;
                    ushort          loopLoc = loopEnd.JumpLoc;
                    if (isForLoop && conditionIdx > 0 && statements[conditionIdx - 1] is AssignStatement assignStatement)
                    {
                        forInit   = assignStatement;
                        skipStart = conditionIdx - 1;
                        numToSkip++;
                        loopLoc = positions[assignStatement];
                    }

                    Statement  loop;
                    Expression condition = conditionalJump.Condition;
                    if (isForLoop)
                    {
                        continueToPos = positions[statementBeforeEndOfLoop];
                        loopBody.Statements.RemoveAt(loopBody.Statements.Count - 1);
                        loop = new ForLoop(forInit, condition, update, loopBody);
                    }
                    else
                    {
                        loop = new WhileLoop(condition, loopBody);
                    }

                    //recurse into body of loop
                    DecompileLoopsAndIfs(loopBody.Statements, positions, true);

                    //convert unconditional jumps into continue and break
                    const int sizeOfUnconditionalJump = 3;
                    ConvertJumps(loopBody, continueToPos, loopEnd.JumpLoc, curPos + sizeOfUnconditionalJump);

                    statements.RemoveRange(skipStart, numToSkip);
                    statements.Insert(skipStart, loop);
                    StatementLocations[loopLoc] = loop;
                    positions[loop]             = loopLoc;

                    i = skipStart;
                }
示例#21
0
        private AltRule createSeed(SymbolPosition position,
                                   List <Production> productions,
                                   bool doubled,  // should we double the seed right at the start
                                   string lhsSymbolName,
                                   IEnumerable <string> elementTypeNames,
                                   params RhsSymbol[] symbols)
        {
            RhsSymbol[] init_symbols = symbols.Where(it => !it.SkipInitially).ToArray();

            var main_code = new CodeBody().AddWithIdentifier(CodeWords.New, " ");

            main_code.Append(makeTupleListCode(position, elementTypeNames));
            main_code.AddSnippet("(");

            IEnumerable <CodeBody> code_lists
                = elementTypeNames.Select(it => new CodeBody().AddWithIdentifier(CodeWords.New, " ", CodeWords.List, "<", it, ">{")).ToList();

            // purpose: to handle names in doubled seed mode
            Dictionary <RhsSymbol, string[]> obj_name_substs = new Dictionary <RhsSymbol, string[]>();

            {
                IEnumerable <RhsSymbol> named_symbols = symbols.Where(it => it.ObjName != null);

                if (named_symbols.Any())
                {
                    foreach (Tuple <RhsSymbol, CodeBody> tuple in named_symbols.SyncZip(code_lists))
                    {
                        RhsSymbol nsymbol    = tuple.Item1;
                        CodeBody  lcode      = tuple.Item2;
                        bool      double_sym = doubled && !nsymbol.SkipInitially;

                        string[] name_subst = new string[double_sym ? 2 : 1];
                        obj_name_substs.Add(nsymbol, name_subst);

                        // if we double the element, we have to come up with new names
                        if (double_sym)
                        {
                            name_subst[0] = AutoNames.Double1 + nsymbol.ObjName + "__";
                            name_subst[1] = AutoNames.Double2 + nsymbol.ObjName + "__";
                        }
                        else
                        {
                            name_subst[0] = nsymbol.ObjName;
                        }

                        for (int i = 0; i < (double_sym ? 2 : 1); ++i)
                        {
                            if (i == 1)
                            {
                                lcode.AddSnippet(",");
                            }

                            if (double_sym)
                            {
                                lcode.AddIdentifier(name_subst[i]);
                            }
                            else
                            {
                                lcode.AddIdentifier(nsymbol.ObjName);
                            }
                        }
                    }
                }
            }

            foreach (Tuple <CodeBody, int> code_pair in code_lists.ZipWithIndex())
            {
                code_pair.Item1.AddSnippet("}");

                if (code_pair.Item2 > 0)
                {
                    main_code.AddSnippet(",");
                }
                main_code.Append(code_pair.Item1);
            }

            main_code.AddSnippet(")");

            // in case of doubled seed we have to rename the symbols
            // otherwise just make shallow copies without renaming
            // but since we already set proxy name correctly, we can use shared code for both cases
            var seed_symbols = new LinkedList <RhsSymbol>();

            for (int i = 0; i < (doubled ? 2 : 1); ++i)
            {
                foreach (RhsSymbol sym in (i == 0 ? init_symbols : symbols))
                {
                    if (sym.ObjName == null)
                    {
                        seed_symbols.AddLast(sym.ShallowClone());
                    }
                    else
                    {
                        int s_idx = (i == 1 && sym.SkipInitially) ? 0 : i;
                        seed_symbols.AddLast(sym.Renamed(obj_name_substs[sym][s_idx]));
                    }
                }
            }


            return(AltRule.CreateInternally(position,
                                            // are there any symbols for production
                                            seed_symbols.Any()
                ? new RhsGroup[] { RhsGroup.CreateSequence(position, RepetitionEnum.Once, seed_symbols.Select(it => it.SetSkip(false)).ToArray()) }
                : new RhsGroup[] { },
                                            new CodeMix(CodeMix.SeedComment).AddBody(main_code)));
        }
示例#22
0
 internal FactoryTypeInfo SetParams(CodeBody paramsCode)
 {
     this.Params = paramsCode;
     return(this);
 }
        private ProductionInfo makeBuilderCall(string lhsSymbol,
                                               RecursiveEnum recursive,
                                               AltRule alt,
                                               IEnumerable <SymbolMarked> symbolsMarked,
                                               string treeNodeName)
        {
            // add production with no code
            var prod_info = new ProductionInfo(alt.Position, lhsSymbol, recursive, symbolsMarked.Where(it => it.IsEnabled).Select(it => it.Symbol),
                                               alt.MarkWith);

            CodeBody code_body = null;

            if (alt.Code != null)
            {
                code_body = (alt.Code as CodeMix).BuildBody(symbolsMarked.Where(sym => sym.Symbol.ObjName != null)
                                                            .Select(sym => sym.Symbol.GetCodeArgumentNames().Select(it => Tuple.Create(it, sym.IsEnabled))).Flatten())
                            .Trim();

                string identity_function_on = null;
                // are we just passing one of the parameters?
                if (code_body.IsIdentity)
                {
                    identity_function_on = code_body.IdentityIdentifier;
                }

                foreach (string var_name in code_body.GetVariables())
                {
                    SymbolMarked sym = symbolsMarked
                                       .Where(sm => sm.Symbol.GetCodeArgumentNames().Contains(var_name))
                                       // there could be duplicates so we "prefer" enabled element
                                       .OrderBy(it => it.IsEnabled ? 0 : 1)
                                       .FirstOrDefault();

                    if (sym != null)
                    {
                        sym.IsParamUsed = true;
                    }
                }

                var anon_args = new Dictionary <SymbolMarked, string>();
                foreach (Tuple <SymbolMarked, int> sym_pair in symbolsMarked.ZipWithIndex())
                {
                    if (sym_pair.Item1.Symbol.ObjName == null)
                    {
                        anon_args.Add(sym_pair.Item1, code_body.RegisterNewIdentifier("_" + sym_pair.Item2));
                    }
                }

                IEnumerable <SymbolMarked> arg_symbols = symbolsMarked.Where(it => it.IsEnabled || it.IsParamUsed).ToList();

                // build external function to run the user code
                string func_ref = registerLambda(lhsSymbol,
                                                 arg_symbols.Select(sym => sym.Symbol.GetCodeArgumentTypes(grammar)).Flatten(),
                                                 grammar.TreeNodeName,
                                                 arg_symbols.Select(sym => sym.Symbol.GetCodeArgumentNames()
                                                                    .Select(it => Tuple.Create(it, anon_args.GetOrNull(sym)))).Flatten(),
                                                 code_body);

                // build a lambda with call to a just built function
                // note that our lambda can have fewer arguments than the actual fuction
                // in such case we pass "nulls" for disabled arguments

                // we add nulls to params in order to keep track which arguments comes from which parameters
                IEnumerable <FuncParameter> lambda_params = arg_symbols.Where(it => it.IsEnabled)
                                                            .Select(it => FuncParameter.Create(it.Symbol.ObjName, anon_args.GetOrNull(it), grammar.GetTypeNameOfSymbol(it.Symbol))).ToArray();

                // if the code indicates that this is identity function, then just find out which parameter is passed along
                if (identity_function_on != null)
                {
                    // we can fail for two reasons here:
                    // (1) ok -- single variable we found in the code body is not a parameter, but global variable
                    // (2) BAD -- we have case of unpacking the data, and that case so far we cannot handle
                    // ad.2) consider such rule as
                    // x -> (a b)+ { b };
                    // "a" and "b" will be handled as tuple of lists
                    // so in entry function we will get a tuple, and then we will call actuall user action code
                    // some "__function_13__(a,b)" which returns the "b"
                    // so we could compute index for inner parameter (for "b" it is 1)
                    // but we cannot compute index for outer function, because there is no index for "b" at all
                    // there is only one parameter -- tuple -- holding "a" (in Item1) and "b" (in Item2) at the same time
                    // so if anything we would have to introduce some combo index:
                    // outer index --> optional unpacking index --> inner index
                    // too much trouble for now
                    Option <int> index = lambda_params.Select(it => it.Name)
                                         .ZipWithIndex().Where(it => it.Item1 == identity_function_on).Select(it => it.Item2).OptSingle();
                    if (index.HasValue)
                    {
                        prod_info.IdentityOuterFunctionParamIndex = index.Value;
                    }
                }

                prod_info.ActionCode = CodeLambda.CreateProxy(
                    lhsSymbol,
                    // lambda arguments
                    lambda_params,
                    treeNodeName,
                    func_ref,

                    arg_symbols.Select(arg => arg.Symbol.CombinedSymbols == null
                                       // regular symbols
                        ? new[] { new CodeBody().AddIdentifier(arg.IsEnabled ? (arg.Symbol.ObjName ?? anon_args[arg]) : CodeWords.Null) }
                                       // compound symbols, we have to use embedded atomic symbols instead now
                        : arg.Symbol.UnpackTuple(arg.IsEnabled)
                                       )
                    .Flatten());

                prod_info.CodeComment = alt.Code.Comment;
            }

            return(prod_info);
        }
示例#24
0
        public void Update()
        {
            if (playing)
            {
                Input.mbPos   = mbPosPast;
                Input.mbWheel = 0;

                if (past != null && past.frame == _frame - 1)
                {
                    past.PlayPast();
                    past = null;
                }

                if (future == null)
                {
                    if (reader.BaseStream.Position < reader.BaseStream.Length)
                    {
                        future = GetFuture();

                        Future GetFuture()
                        {
                            Future future = new Future();

                            while (true)
                            {
                                CodeBody code = (CodeBody)reader.ReadByte();
                                switch (code)
                                {
                                case CodeBody.Frame:
                                    future.frame             = lastFrameWrittenToStream + reader.ReadInt32();
                                    lastFrameWrittenToStream = future.frame;
                                    return(future);

                                case CodeBody.MousePos:
                                    future.mbPos = reader.ReadVector2();
                                    break;

                                case CodeBody.MouseWheel:
                                    future.mbWheel = reader.ReadInt32();
                                    break;

                                case CodeBody.KeyPressed:
                                    future.pressed.Add(Input.keys[reader.ReadInt16()]);
                                    break;

                                case CodeBody.KeyReleased:
                                    future.released.Add(Input.keys[reader.ReadInt16()]);
                                    break;

                                default:
                                    throw new Exception();
                                }
                            }
                        }
                    }
                    else
                    {
                        // stop playing
                        //if (_frame >= frames)
                        //{
                        //}
                        Input.ClearKeys();
                        _playing         = false;
                        Input.blockInput = false;

                        if (FinishPlaying != null)
                        {
                            FinishPlaying(this, EventArgs.Empty);
                        }
                        return;
                    }
                }

                if (future.frame == _frame)
                {
                    future.Play();
                    past   = future;
                    future = null;
                }
                else if (future.frame < _frame)
                {
                    throw new Exception();
                }


                mbPosPast = Input.mbPos;
            }

            if (recording)
            {
                // update format:
                // 1(byte): frame distance to last input frame
                //      frame(int)
                // 2(byte): mouse
                //      x(Vector2)
                // 3(byte): mouseWheel
                //      wheel(int)
                // 4(byte): key pressed
                //      id(short)
                // 5(byte): key released
                //      id(short)

                long prevStreamPos = writer.BaseStream.Position;

                if (mouseInput)
                {
                    #region Mouse

                    if (Input.mbPos != mbPosPast)
                    {
                        writer.Write((byte)CodeBody.MousePos);
                        writer.Write(Input.mbPos);
                        mbPosPast = Input.mbPos;
                    }

                    if (Input.mbWheel != 0)
                    {
                        writer.Write((byte)CodeBody.MouseWheel);
                        writer.Write(Input.mbWheel);
                    }

                    #endregion
                }

                #region Keys

                for (int i = 0; i < keysInput.Length; i++)
                {
                    if (keysInput[i].pressed)
                    {
                        writer.Write((byte)CodeBody.KeyPressed);
                        writer.Write(keysInput[i].id);
                    }
                    else if (keysInput[i].released)
                    {
                        writer.Write((byte)CodeBody.KeyReleased);
                        writer.Write(keysInput[i].id);
                    }
                }

                #endregion

                if (prevStreamPos != writer.BaseStream.Position)
                {
                    writer.Write((byte)CodeBody.Frame);
                    writer.Write(_frame - lastFrameWrittenToStream);
                    lastFrameWrittenToStream = _frame;

                    writer.Flush();
                }
            }

            if (recording || playing)
            {
                _frame++;
            }
        }
示例#25
0
 internal FactoryTypeInfo SetCode(CodeBody code)
 {
     this.Code = code;
     return(this);
 }
示例#26
0
        public Function TryParseFunction()
        {
            Func <ASTNode> stubParser = () =>
            {
                var specs = ParseSpecifiers(GlobalLists.FunctionSpecifiers);

                if (Tokens.ConsumeToken(TokenType.Function) == null)
                {
                    return(null);
                }

                Token <String> returnType = null, name = null;

                var firstString = Tokens.ConsumeToken(TokenType.Word);
                if (firstString == null)
                {
                    return(Error("Expected function name or return type!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var secondString = Tokens.ConsumeToken(TokenType.Word);
                if (secondString == null)
                {
                    name = firstString;
                }
                else
                {
                    returnType = firstString;
                    name       = secondString;
                }

                VariableType retVarType = returnType != null ?
                                          new VariableType(returnType.Value, returnType.StartPosition, returnType.EndPosition) : null;

                if (Tokens.ConsumeToken(TokenType.LeftParenth) == null)
                {
                    return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var parameters = new List <FunctionParameter>();
                while (CurrentTokenType != TokenType.RightParenth)
                {
                    var param = TryParseParameter();
                    if (param == null)
                    {
                        return(Error("Malformed parameter!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }

                    parameters.Add(param);
                    if (Tokens.ConsumeToken(TokenType.Comma) == null && CurrentTokenType != TokenType.RightParenth)
                    {
                        return(Error("Unexpected parameter content!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }
                }

                if (Tokens.ConsumeToken(TokenType.RightParenth) == null)
                {
                    return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                CodeBody       body = new CodeBody(null, CurrentPosition, CurrentPosition);
                SourcePosition bodyStart = null, bodyEnd = null;
                if (Tokens.ConsumeToken(TokenType.SemiColon) == null)
                {
                    if (!ParseScopeSpan(TokenType.LeftBracket, TokenType.RightBracket, out bodyStart, out bodyEnd))
                    {
                        return(Error("Malformed function body!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }

                    body = new CodeBody(null, bodyStart, bodyEnd);
                }

                return(new Function(name.Value, retVarType, body, specs, parameters, name.StartPosition, name.EndPosition));
            };

            return((Function)Tokens.TryGetTree(stubParser));
        }
示例#27
0
 internal static IEnumerable <LexItem> AsDetectedStatement(IEnumerable <ILexPattern> patterns, IEnumerable <IEnumerable <string> > contextTokens, string token,
                                                           string state, CodeBody code, bool resolved = false)
 {
     // we have to build up at least one empty context, otherwise we will not produce any elements
     return(populateContexts(contextTokens).Select(ctx => new LexItem(patterns, ctx, token, state, !code.HasStatement, code, resolved)).ToArray());
 }
示例#28
0
        public State TryParseState()
        {
            Func <ASTNode> stateSkeletonParser = () =>
            {
                var specs = ParseSpecifiers(GlobalLists.StateSpecifiers);

                if (Tokens.ConsumeToken(TokenType.State) == null)
                {
                    return(null);
                }

                var name = Tokens.ConsumeToken(TokenType.Word);
                if (name == null)
                {
                    return(Error("Expected state name!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var parent = TryParseParent();

                if (Tokens.ConsumeToken(TokenType.LeftBracket) == null)
                {
                    return(Error("Expected '{'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                List <Function> ignores = new List <Function>();
                if (Tokens.ConsumeToken(TokenType.Ignores) != null)
                {
                    do
                    {
                        VariableIdentifier variable = TryParseVariable();
                        if (variable == null)
                        {
                            return(Error("Malformed ignore statement!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                        }

                        ignores.Add(new Function(variable.Name, null, null, null, null, variable.StartPos, variable.EndPos));
                    } while (Tokens.ConsumeToken(TokenType.Comma) != null);

                    if (Tokens.ConsumeToken(TokenType.SemiColon) == null)
                    {
                        return(Error("Expected semi-colon!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }
                }

                var      funcs = new List <Function>();
                Function func  = TryParseFunction();
                while (func != null)
                {
                    funcs.Add(func);
                    func = TryParseFunction();
                }

                var bodyStart = Tokens.CurrentItem.StartPosition;
                while (Tokens.CurrentItem.Type != TokenType.RightBracket && !Tokens.AtEnd())
                {
                    Tokens.Advance();
                }
                var bodyEnd = Tokens.CurrentItem.StartPosition;

                if (Tokens.ConsumeToken(TokenType.RightBracket) == null)
                {
                    return(Error("Expected '}'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var body        = new CodeBody(new List <Statement>(), bodyStart, bodyEnd);
                var parentState = parent != null ? new State(parent.Name, null, null, null, null, null, null, parent.StartPos, parent.EndPos) : null;
                return(new State(name.Value, body, specs, parentState, funcs, ignores, null, name.StartPosition, name.EndPosition));
            };

            return((State)Tokens.TryGetTree(stateSkeletonParser));
        }
示例#29
0
        private static CodeBody makeListCode(string elementTypeName)
        {
            var code = new CodeBody().AddWithIdentifier(CodeWords.List, "<", elementTypeName, ">");

            return(code);
        }
示例#30
0
        public OperatorDeclaration TryParseOperatorDecl()
        {
            Func <ASTNode> operatorParser = () =>
            {
                var specs = ParseSpecifiers(GlobalLists.FunctionSpecifiers);

                var token = Tokens.ConsumeToken(TokenType.Operator) ??
                            Tokens.ConsumeToken(TokenType.PreOperator) ??
                            Tokens.ConsumeToken(TokenType.PostOperator) ??
                            new Token <String>(TokenType.INVALID);

                if (token.Type == TokenType.INVALID)
                {
                    return(null);
                }

                Token <String> precedence = null;
                if (token.Type == TokenType.Operator)
                {
                    if (Tokens.ConsumeToken(TokenType.LeftParenth) == null)
                    {
                        return(Error("Expected '('! (Did you forget to specify operator precedence?)", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }

                    precedence = Tokens.ConsumeToken(TokenType.IntegerNumber);
                    if (precedence == null)
                    {
                        return(Error("Expected an integer number!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }

                    if (Tokens.ConsumeToken(TokenType.RightParenth) == null)
                    {
                        return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }
                }

                Token <String> returnType = null, name = null;
                var            firstString = TryParseOperatorIdentifier();
                if (firstString == null)
                {
                    return(Error("Expected operator name or return type!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var secondString = TryParseOperatorIdentifier();
                if (secondString == null)
                {
                    name = firstString;
                }
                else
                {
                    returnType = firstString;
                    name       = secondString;
                }

                VariableType retVarType = returnType != null ?
                                          new VariableType(returnType.Value, returnType.StartPosition, returnType.EndPosition) : null;

                if (Tokens.ConsumeToken(TokenType.LeftParenth) == null)
                {
                    return(Error("Expected '('!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var operands = new List <FunctionParameter>();
                while (CurrentTokenType != TokenType.RightParenth)
                {
                    var operand = TryParseParameter();
                    if (operand == null)
                    {
                        return(Error("Malformed operand!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }

                    operands.Add(operand);
                    if (Tokens.ConsumeToken(TokenType.Comma) == null && CurrentTokenType != TokenType.RightParenth)
                    {
                        return(Error("Unexpected operand content!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }
                }

                if (token.Type == TokenType.Operator && operands.Count != 2)
                {
                    return(Error("In-fix operators requires exactly 2 parameters!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                else if (token.Type != TokenType.Operator && operands.Count != 1)
                {
                    return(Error("Post/Pre-fix operators requires exactly 1 parameter!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                if (Tokens.ConsumeToken(TokenType.RightParenth) == null)
                {
                    return(Error("Expected ')'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                CodeBody       body = new CodeBody(null, CurrentPosition, CurrentPosition);
                SourcePosition bodyStart = null, bodyEnd = null;
                if (Tokens.ConsumeToken(TokenType.SemiColon) == null)
                {
                    if (!ParseScopeSpan(TokenType.LeftBracket, TokenType.RightBracket, out bodyStart, out bodyEnd))
                    {
                        return(Error("Malformed operator body!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }

                    body = new CodeBody(null, bodyStart, bodyEnd);
                }

                // TODO: determine if operator should be a delimiter! (should only symbol-based ones be?)
                if (token.Type == TokenType.PreOperator)
                {
                    return(new PreOpDeclaration(name.Value, false, body, retVarType, operands.First(), specs, name.StartPosition, name.EndPosition));
                }
                else if (token.Type == TokenType.PostOperator)
                {
                    return(new PostOpDeclaration(name.Value, false, body, retVarType, operands.First(), specs, name.StartPosition, name.EndPosition));
                }
                else
                {
                    return(new InOpDeclaration(name.Value, Int32.Parse(precedence.Value), false, body, retVarType,
                                               operands.First(), operands.Last(), specs, name.StartPosition, name.EndPosition));
                }
            };

            return((OperatorDeclaration)Tokens.TryGetTree(operatorParser));
        }