示例#1
0
 void CompileBlockReturn(ParseTree ast, Types.Environment env)
 {
     var blockName = ast.Children.ElementAt (0);
     var result = ast.Children.ElementAt (1);
     this.CompileAst (blockName, env, true, true);
     this.CompileAst (result, env, true, true);
     this.Gen (Instruction.Opcodes.BlockReturn, null, ast);
 }
示例#2
0
文件: Parser.cs 项目: ichaos/Shovel
 ParseTree WithAnchoredParseTree(int startPos, ParseTree.Labels label, Action<ParseTree> action)
 {
     ParseTree result = new ParseTree ();
     result.StartPos = startPos;
     result.Label = label;
     action (result);
     result.EndPos = this.LastToken ().EndPos;
     return result;
 }
示例#3
0
文件: Parser.cs 项目: ichaos/Shovel
 static ParseTree GetFalseParseTree()
 {
     if (Parser.falseParseTree == null) {
         Parser.falseParseTree = new ParseTree () {
             Label = ParseTree.Labels.Bool,
             Content = "false",
             StartPos = -1,
             EndPos = -1
         };
     }
     return Parser.falseParseTree;
 }
示例#4
0
文件: Parser.cs 项目: ichaos/Shovel
 // Gref is short for 'generic reference'.
 ParseTree ParseIdentifierOrCallOrRef(ParseTree forcedStart = null)
 {
     var start = forcedStart;
     if (start == null) {
         start = this.ParseParenthesizedOrName ();
     }
     if (this.TokenIs (Token.Types.Punctuation, ".")) {
         var first = this.WithAnchoredParseTree (start.StartPos, ParseTree.Labels.Call, pt => {
             this.RequireTokenExactly (Token.Types.Punctuation, ".");
             pt.Children = new ParseTree[] {
                 this.MakePrim0ParseTree ("svm_gref_dot"),
                 start,
                 this.ParseNameAsString ()
             };
         }
         );
         return this.ParseIdentifierOrCallOrRef (first);
     } else if (this.TokenIs (Token.Types.Punctuation, "(")) {
         var first = this.WithAnchoredParseTree (start.StartPos, ParseTree.Labels.Call, pt => {
             var children = new List<ParseTree> ();
             children.Add (start);
             children.AddRange (this.ParseList (
                 this.ParseExpression,
                 Parser.OpenParenthesis, Parser.Comma, Parser.CloseParenthesis)
             );
             pt.Children = children;
         }
         );
         return this.ParseIdentifierOrCallOrRef (first);
     } else if (this.TokenIs (Token.Types.Punctuation, "[")) {
         ParseTree grefParseTree = null;
         int grefStartPos = 0;
         int grefEndPos = 0;
         var result = this.WithAnchoredParseTree (start.StartPos, ParseTree.Labels.Call, pt => {
             grefStartPos = this.CurrentToken ().StartPos;
             this.RequireTokenExactly (Token.Types.Punctuation, "[");
             grefParseTree = this.MakePrim0ParseTree ("svm_gref");
             pt.Children = new ParseTree[] {
                 grefParseTree,
                 start,
                 this.ParseExpression ()
             };
             this.ConsumeToken (Token.Types.Punctuation, "]");
             grefEndPos = this.LastToken ().EndPos;
         }
         );
         grefParseTree.StartPos = grefStartPos;
         grefParseTree.EndPos = grefEndPos;
         return this.ParseIdentifierOrCallOrRef(result);
     } else {
         return start;
     }
 }
示例#5
0
文件: Parser.cs 项目: ichaos/Shovel
 ParseTree PostProcessLogicalOr(ParseTree arg)
 {
     return this.MaybeRewriteAsIfExpression (
         arg, "||",
         (t1, t2) => new ParseTree[] { t1, Parser.GetTrueParseTree (), t2 });
 }
示例#6
0
 // Gref is short for 'generic reference'.
 bool IsGrefCall(ParseTree ast)
 {
     if (ast.Label == ParseTree.Labels.Call) {
         if (ast.Children.Count () > 0) {
             var fn = ast.Children.First ();
             if (fn.Label == ParseTree.Labels.Prim0) {
                 if (fn.Content == "svm_gref" || fn.Content == "svm_gref_dot") {
                     return true;
                 }
             }
         }
     }
     return false;
 }
示例#7
0
文件: Parser.cs 项目: ichaos/Shovel
        ParseTree MaybeRewriteAsIfExpression(
			ParseTree parseTree, 
			string opName, 
			Func<ParseTree, ParseTree, IEnumerable<ParseTree>> ifChildren)
        {
            if (this.IsRequiredPrimitiveCall (parseTree, opName)) {
                var operands = parseTree.Children.ToArray ();
                var op = operands [0];
                var t1 = operands [1];
                var t2 = operands [2];
                return new ParseTree () {
                    Label = ParseTree.Labels.If,
                    StartPos = op.StartPos,
                    EndPos = op.EndPos,
                    Children = ifChildren(t1, t2)
                };
            } else {
                return parseTree;
            }
        }
示例#8
0
 void CompileIf(ParseTree ast, Types.Environment env, bool useVal, bool more)
 {
     if (more) {
         var l1 = this.GenLabel ();
         var l2 = this.GenLabel ();
         var pred = ast.Children.ElementAt (0);
         this.CompileAst (pred, env, true, true);
         this.Gen (Instruction.Opcodes.Fjump, l1);
         var thenAction = ast.Children.ElementAt (1);
         this.CompileAst (thenAction, env, useVal, true);
         this.Gen (Instruction.Opcodes.Jump, l2);
         this.Gen (Instruction.Opcodes.Label, l1);
         var elseAction = ast.Children.ElementAt (2);
         this.CompileAst (elseAction, env, useVal, true);
         this.Gen (Instruction.Opcodes.Label, l2);
     } else {
         var l1 = this.GenLabel ();
         var pred = ast.Children.ElementAt (0);
         this.CompileAst (pred, env, true, true);
         this.Gen (Instruction.Opcodes.Fjump, l1);
         var thenAction = ast.Children.ElementAt (1);
         this.CompileAst (thenAction, env, useVal, false);
         this.Gen (Instruction.Opcodes.Label, l1);
         var elseAction = ast.Children.ElementAt (2);
         this.CompileAst (elseAction, env, useVal, false);
     }
 }
示例#9
0
 void CompileName(ParseTree ast, Types.Environment env, bool useVal, bool more)
 {
     var varName = ast.Content;
     this.Gen (Instruction.Opcodes.Lget,
               this.FindName (varName, env, ast.StartPos, ast.EndPos),
               ast);
     this.FinishInstruction (useVal, more);
 }
示例#10
0
 void CompileFnBody(ParseTree args, ParseTree body, Types.Environment env)
 {
     if (args.Children.Count () > 0) {
         var newEnv = this.EmptyEnv ();
         newEnv.Next = env;
         foreach (var arg in args.Children) {
             this.ExtendFrame (newEnv, arg.Content, arg, false);
         }
         var varNames = args.Children.Select (arg => arg.Content).ToArray ();
         this.Gen (
             Instruction.Opcodes.NewFrame, varNames,
             startPos: args.Children.First ().StartPos,
             endPos: args.Children.Last ().EndPos);
         this.Gen (Instruction.Opcodes.Args, varNames.Length);
         this.CompileAst (body, newEnv, true, false);
     } else {
         this.CompileAst (body, env, true, false);
     }
 }
示例#11
0
 void CompileFuncall(ParseTree ast, Types.Environment env, bool useVal, bool more)
 {
     foreach (var child in ast.Children.Skip(1)) {
         this.CompileAst (child, env, true, true);
     }
     var funAst = ast.Children.First ();
     var compiledAsInstruction = false;
     if (funAst.Label == ParseTree.Labels.Prim0) {
         compiledAsInstruction =
             this.CompiledAsInstruction (funAst, ast.Children.Count () - 1, useVal, more);
     }
     if (!compiledAsInstruction) {
         this.CompileAst (funAst, env, true, true);
         if (more) {
             this.Gen (Instruction.Opcodes.Call, ast.Children.Count () - 1, ast);
             if (!useVal) {
                 this.Gen (Instruction.Opcodes.Pop);
             }
         } else {
             this.Gen (Instruction.Opcodes.CallJ, ast.Children.Count () - 1, ast);
         }
     }
 }
示例#12
0
 void CompileFn(ParseTree ast, Types.Environment env, bool useVal, bool more)
 {
     if (useVal) {
         var fn = this.GenLabel ("FN");
         var l = this.GenLabel ();
         this.Gen (Instruction.Opcodes.Jump, l);
         this.Gen (Instruction.Opcodes.Label, fn, ast);
         var args = ast.Children.ElementAt (0);
         var body = ast.Children.ElementAt (1);
         this.CompileFnBody (args, body, env);
         this.Gen (Instruction.Opcodes.Label, l);
         var arity = args.Children.Count();
         var hasCollectParams = args.Children.Any(pt => pt.Label == ParseTree.Labels.CollectName);
         if (hasCollectParams) {
             arity --;
             arity += Callable.CollectParamsArityModifier;
         }
         this.Gen (Instruction.Opcodes.Fn, new object[] {
             fn,
             arity
         });
         if (!more) {
             this.Gen (Instruction.Opcodes.Return);
         }
     }
 }
示例#13
0
 bool CompiledAsInstruction(ParseTree funAst, int actualArity, bool useVal, bool more)
 {
     foreach (var pair in compilableAsInstructions) {
         if (pair.Item1 == funAst.Content) {
             if (actualArity == pair.Item3) {
                 this.Gen (pair.Item2, startPos: funAst.StartPos, endPos: funAst.EndPos);
                 this.FinishInstruction (useVal, more);
             } else {
                 var message = String.Format (
                     "Primitive requires {0} arguments, but was called with {1} arguments.",
                     pair.Item3,
                     actualArity);
                 this.RaiseError (funAst.StartPos, funAst.EndPos, message);
             }
             return true;
         }
     }
     return false;
 }
示例#14
0
 void CompileContext(ParseTree ast, bool useVal, bool more)
 {
     this.Gen (Instruction.Opcodes.Context, null, ast);
     FinishInstruction (useVal, more);
 }
示例#15
0
 void ExtendFrame(Types.Environment env, string name, ParseTree nameAst, bool placeHolder)
 {
     var topFrame = env.Frame;
     var previousDefinition = topFrame.EntryFor (name);
     if (previousDefinition != null) {
         if (!previousDefinition.PlaceHolder) {
             var sourceFile = SourceFile.FindSource (this.sources, previousDefinition.FileName);
             var pos = Position.CalculatePosition (sourceFile, previousDefinition.StartPos);
             var message = String.Format (
                 "Variable '{0}' is already defined in this frame in file '{1}', at line {2}, column {3}.",
                 name, pos.FileName, pos.Line, pos.Column);
             this.RaiseError (nameAst.StartPos, nameAst.EndPos, message);
         } else {
             previousDefinition.PlaceHolder = placeHolder;
             if (nameAst != null) {
                 previousDefinition.StartPos = nameAst.StartPos;
             } else {
                 previousDefinition.StartPos = 0;
             }
         }
     } else {
         int currentPos = 0;
         if (nameAst != null) {
             currentPos = nameAst.StartPos;
         }
         var newVar = new EnvVar ()
         {
             Name = name,
             FileName = this.fileName,
             Place = topFrame.Vars.Count,
             StartPos = currentPos,
             PlaceHolder = placeHolder
         };
         topFrame.Vars.Add (newVar);
     }
 }
示例#16
0
 void CompileNamedBlock(ParseTree ast, Types.Environment env, bool useVal, bool more)
 {
     var blockName = ast.Children.ElementAt (0);
     var blockContents = ast.Children.ElementAt (1);
     var blockEnd = this.GenLabel ("BE");
     this.CompileAst (blockName, env, true, true);
     this.Gen (Instruction.Opcodes.Block, blockEnd, ast);
     this.CompileAst (blockContents, env, true, true);
     this.Gen (Instruction.Opcodes.Label, blockEnd);
     this.Gen (Instruction.Opcodes.PopBlock, null, ast);
     this.FinishInstruction (useVal, more);
 }
示例#17
0
 void Gen(Instruction.Opcodes opcode,
           object arguments = null,
           ParseTree pos = null,
           string comments = null,
           int? startPos = null,
           int? endPos = null)
 {
     var instruction = new Instruction ()
     {
         Opcode = opcode,
         Arguments = arguments,
         Comments = comments
     };
     if (startPos != null) {
         instruction.StartPos = startPos;
     } else if (pos != null && pos.StartPos != -1) {
         instruction.StartPos = pos.StartPos;
     }
     if (endPos != null) {
         instruction.EndPos = endPos;
     } else if (pos != null && pos.EndPos != -1) {
         instruction.EndPos = pos.EndPos;
     }
     this.bytecode.Add (instruction);
 }
示例#18
0
 void CompilePrim0(ParseTree ast, bool useVal, bool more)
 {
     this.Gen (Instruction.Opcodes.Prim0, ast.Content, ast);
     FinishInstruction (useVal, more);
 }
示例#19
0
文件: Parser.cs 项目: ichaos/Shovel
 bool IsRequiredPrimitiveCall(ParseTree parseTree, string opName)
 {
     if (parseTree.Label == ParseTree.Labels.Call) {
         var op = parseTree.Children.First ();
         if (op.Label == ParseTree.Labels.Prim0 && op.Content == opName) {
             return true;
         }
     }
     return false;
 }
示例#20
0
 void CompileSet(ParseTree ast, Types.Environment env, bool useVal, bool more)
 {
     var leftHandSide = ast.Children.First ();
     if (leftHandSide.Label == ParseTree.Labels.Name) {
         this.CompileAst (ast.Children.ElementAt (2), env, true, true);
         this.CompileSetVar (leftHandSide.Content, env, useVal, more, ast);
     } else {
         if (!this.IsGrefCall (leftHandSide)) {
             this.RaiseError (
                 ast.StartPos, ast.EndPos,
                 "Assignment only supported for names, arrays and hashes.");
         }
         var arrayOrHash = leftHandSide.Children.ElementAt (1);
         var index = leftHandSide.Children.ElementAt (2);
         var literalStringIndex = index.Label == ParseTree.Labels.String;
         var setOperator = leftHandSide.Children.ElementAt (0);
         var primitiveParseTree = new ParseTree ()
         {
             Label = ParseTree.Labels.Prim0,
             StartPos = setOperator.StartPos,
             EndPos = setOperator.EndPos,
             Content = literalStringIndex ? "svm_set_dot_indexed" : "svm_set_indexed"
         };
         var rightHandSide = ast.Children.ElementAt (2);
         var callParseTree = new ParseTree ()
         {
             Label = ParseTree.Labels.Call,
             StartPos = ast.StartPos,
             EndPos = ast.EndPos,
             Children = new ParseTree[] {
                 primitiveParseTree,
                 arrayOrHash,
                 index,
                 rightHandSide
             }
         };
         this.CompileAst (callParseTree, env, useVal, more);
     }
 }
示例#21
0
文件: Parser.cs 项目: ichaos/Shovel
 ParseTree ParseAssignment(ParseTree expr)
 {
     return this.WithAnchoredParseTree (expr.StartPos, ParseTree.Labels.Assignment, pt => {
         pt.Children = new ParseTree[] {
             expr,
             this.TokenAsParseTree (ParseTree.Labels.Prim0),
             this.ParseExpression () };
     }
     );
 }
示例#22
0
 void CompileSetVar(string name, Types.Environment env, bool useVal, bool more, ParseTree astForPos)
 {
     this.Gen (
         Instruction.Opcodes.Lset,
         this.FindName (name, env, astForPos.StartPos, astForPos.EndPos),
         astForPos);
     this.FinishInstruction (useVal, more);
 }
示例#23
0
文件: Parser.cs 项目: ichaos/Shovel
 ParseTree PostProcessLogicalAnd(ParseTree arg)
 {
     return this.MaybeRewriteAsIfExpression (
         arg, "&&",
         (t1, t2) => new ParseTree[] { t1, t2, Parser.GetFalseParseTree () });
 }
示例#24
0
 void CompileStatements(
     Types.Environment env,
     IEnumerable<ParseTree> dropValueAsts, ParseTree valueAst,
     bool more)
 {
     foreach (var ast in dropValueAsts) {
         this.CompileAst (ast, env, false, true);
     }
     this.CompileAst (valueAst, env, true, more);
 }
示例#25
0
文件: Parser.cs 项目: ichaos/Shovel
 ParseTree TokenAsParseTree(ParseTree.Labels prim0)
 {
     return this.WithNewParseTree (prim0, pt => {
         pt.Content = this.CurrentToken ().Content;
         this.NextToken ();
     }
     );
 }
示例#26
0
 void CompileUserDefinedPrimitive(ParseTree ast, bool useVal, bool more)
 {
     this.Gen (Instruction.Opcodes.Prim, ast.Content.Substring (1), ast);
     FinishInstruction (useVal, more);
 }
示例#27
0
文件: Parser.cs 项目: ichaos/Shovel
 ParseTree WithNewParseTree(ParseTree.Labels label, Action<ParseTree> action)
 {
     ParseTree result = new ParseTree ();
     result.StartPos = this.CurrentToken ().StartPos;
     result.Label = label;
     action (result);
     result.EndPos = this.LastToken ().EndPos;
     return result;
 }
示例#28
0
 void CompileVar(ParseTree ast, Types.Environment env, bool useVal, bool more)
 {
     var nameAst = ast.Children.ElementAt (0);
     var name = nameAst.Content;
     this.ExtendFrame (env, name, nameAst, false);
     this.CompileAst (ast.Children.ElementAt (1), env, true, true);
     this.CompileSetVar (name, env, useVal, more, ast);
 }
示例#29
0
文件: Parser.cs 项目: ichaos/Shovel
 static ParseTree GetNullParseTree()
 {
     if (Parser.nullParseTree == null) {
         Parser.nullParseTree = new ParseTree() {
             Label = ParseTree.Labels.Void,
             Content = "null",
             StartPos = -1,
             EndPos = -1
         };
     }
     return Parser.nullParseTree;
 }
示例#30
0
 object CompileAtomValue(ParseTree.Labels label, string content)
 {
     switch (label) {
     case ParseTree.Labels.Number:
         {
             double doubleResult;
             long longResult;
             if (long.TryParse (content, out longResult)) {
                 return Value.MakeInt (longResult);
             } else if (double.TryParse (content, out doubleResult)) {
                 return Value.MakeFloat (doubleResult);
             }
         }
         Utils.Panic ();
         return null;
     case ParseTree.Labels.String:
         return Value.Make (content.Substring (1, content.Length - 2));
     case ParseTree.Labels.Bool:
         switch (content) {
         case "true":
             return Value.Make (true);
         case "false":
             return Value.Make (false);
         default:
             Utils.Panic ();
             return null;
         }
     case ParseTree.Labels.Void:
         return Value.Make ();
     default:
         Utils.Panic ();
         return null;
     }
 }