/* primaryexp -> prefixexp { `.' NAME | index | `:' NAME funcargs | funcargs } */ private AST.Expression ParsePrimaryExpr() { AST.Expression prefixExp; /* prefixexp -> NAME | '(' expr ')' */ if (Stream.IsName()) { prefixExp = new AST.NameExpression(Stream.GetName().Value); Stream.MoveNext(); } else if (Stream.IsKeyword("(")) { Stream.MoveNext(); prefixExp = new AST.ParenExpression(ParseExpression()); Stream.GetKeywordAndMove(")"); } else { throw new ParserException(); } AST.Expression primaryExp = prefixExp; while (true) { if (Stream.IsKeyword(".")) { Stream.MoveNext(); String lookupName = Stream.GetName().Value; Stream.MoveNext(); primaryExp = new AST.LookupExpression(primaryExp, lookupName); } else if (Stream.IsKeyword("[")) /* index -> '[' expr ']' */ { Stream.MoveNext(); primaryExp = new AST.IndexExpression(primaryExp, ParseExpression()); Stream.GetKeywordAndMove("]"); } else if (Stream.IsKeyword(":")) { Stream.MoveNext(); String functionName = Stream.GetName().Value; Stream.MoveNext(); primaryExp = new AST.SelfLookupExpression(primaryExp, functionName); List<AST.Expression> args = ParseFuncArgs(); primaryExp = new AST.FunctionApplicationExpression(primaryExp, args); } else if (Stream.IsKeyword("(") || Stream.IsKeyword("{") || Stream.IsString()) { List<AST.Expression> args = ParseFuncArgs(); primaryExp = new AST.FunctionApplicationExpression(primaryExp, args); } else { break; } } return primaryExp; }
public void Visit(AST.FunctionStatement statement) { bool isSelfFunction = statement.SelfName != null; bool isGlobal = !isSelfFunction && statement.FieldNames.Count == 0; if (!isGlobal) { // Get the table AST.Expression expr = new AST.NameExpression(statement.MainName); if (statement.FieldNames.Count > 0) { foreach (String field in statement.FieldNames.GetRange(0, statement.FieldNames.Count - 1)) { expr = new AST.LookupExpression(expr, field); } if (isSelfFunction) { expr = new AST.LookupExpression(expr, statement.FieldNames.Last()); } } expr.Visit(new ExpressionCompiler(State, 1)); // Get the key if (isSelfFunction) { State.bytecodes.Add(VirtualMachine.OpCodes.MakeLOADK(State.AddConstant(statement.SelfName))); State.stackPosition++; } else { State.bytecodes.Add(VirtualMachine.OpCodes.MakeLOADK(State.AddConstant(statement.FieldNames.Last()))); State.stackPosition++; } } FunctionCompiler funcCompiler = new FunctionCompiler(State, statement.Body, isSelfFunction); VirtualMachine.Function function = new VirtualMachine.Function(funcCompiler.State.bytecodes.ToArray(), funcCompiler.State.constants.ToArray(), Guid.NewGuid().ToString(), funcCompiler.State.childFunctions, funcCompiler.State.positions, statement.MainName); State.childFunctions.Add(function); State.bytecodes.Add(VirtualMachine.OpCodes.MakeCLOSURE(State.AddConstant(function.Id))); State.stackPosition++; if (!isGlobal) { State.bytecodes.Add(VirtualMachine.OpCodes.PUTTABLE); State.stackPosition -= 3; } else { if (State.stackVars.ContainsKey(statement.MainName)) { State.bytecodes.Add(VirtualMachine.OpCodes.MakePUTSTACK(State.stackPosition - State.stackVars[statement.MainName])); State.stackPosition--; } else { State.bytecodes.Add(VirtualMachine.OpCodes.MakePUTGLOBAL(State.AddConstant(statement.MainName))); State.stackPosition--; } } }