private void AssignmentPreprocessor(AST.Node lhs) { if (!(lhs is AST.Identifier)) { return; // only need to handle simple assignments } if (!this.isfunction) { return; } AST.Identifier target = (AST.Identifier)lhs; if (target.Type != AST.IdentifierType.UnQualifiedName) { return; } if (target.IsEnclosed) { if (this.variables.LocalAssignment.ContainsKey(target.Name)) { // Found the variable already used in a local assignment target.IsEnclosed = false; this.variables.LocalAssignment[target.Name].Add(target); } else { if (!this.variables.GlobalAssignment.ContainsKey(target.Name)) { // variable did not exists currently as global assignment this.variables.GlobalAssignment[target.Name] = new List <AST.Identifier>(); } // add the target as a global assignment target this.variables.GlobalAssignment[target.Name].Add(target); } } else { if (!this.variables.LocalAssignment.ContainsKey(target.Name)) { this.variables.LocalAssignment[target.Name] = new List <AST.Identifier>(); } if (this.variables.GlobalAssignment.ContainsKey(target.Name)) { // found the same variable as a global assignment target // move it to the local assignments foreach (AST.Identifier item in this.variables.GlobalAssignment[target.Name]) { item.IsEnclosed = false; this.variables.LocalAssignment[target.Name].Add(item); } // remove from the global assignments' list this.variables.GlobalAssignment.Remove(target.Name); } this.variables.LocalAssignment[target.Name].Add(target); } }
public void BuildFunctionsAndVariables(AST.Node root) { var variableUsages = new Dictionary <AST.VariableDeclaration, HashSet <AST.FunctionDeclaration> >(); this.BuildVariableUsages(root, null, variableUsages); this.TraverseTree(root, variableUsages); }
public override AST.Node ToAST(Env env) { /// Check the switch statement. Switch sw = env.GetSwitch(); if (sw == null) { throw new Error(Pos, "default statement not in switch statement"); } /// The expression of a case should be constant integer expression. AST.ConstIntegerExpr c = expr.ToASTExpr(env) as AST.ConstIntegerExpr; if (c == null) { throw new Error(Pos, "the expression of a case should be constant integer expression"); } /// No two of the case constant expressions shall have the same value. /// TODO: The conversion. foreach (var e in sw.cases) { if (c.value == e.Item2.value) { throw new Error(Pos, string.Format("duplicate value {0} in case", c.value)); } } string label = env.AllocCaseLabel(); sw.cases.AddLast(new Tuple <string, ConstIntegerExpr>(label, c)); AST.Node s = stmt.ToAST(env); return(new AST.Labeled(label, s)); }
public static void CopyDebugData(AST.Node nodeTo, AST.Node nodeFrom) { if (null != nodeTo && null != nodeFrom) { nodeTo.col = nodeFrom.col; nodeTo.endCol = nodeFrom.endCol; nodeTo.endLine = nodeFrom.endLine; nodeTo.line = nodeFrom.line; } }
public IReadOnlyDictionary <Function, ILabel> CreateIR(AST.Node node) { return(node .ChildrenRecursive() .OfType <AST.FunctionDeclaration>() .Where(fun => !fun.IsForeign) .ToDictionary( decl => decl.Function, decl => this.functionGenerator.GenerateBody(decl.Function, decl))); }
private AST.Node BuildDyadic(AST.Token symbol, AST.Node lhs, AST.Node rhs) { AST.Node node; if (lhs is AST.BuiltInFunction) { /* This will allow the following construct: * ((-)) * 5 */ node = BuildMonadic(((AST.BuiltInFunction)lhs).Function, BuildMonadic(symbol, rhs)); } else if (lhs is AST.BuiltInOperator) { /* This will allow the following construct: * ((-each)) * 5 */ AST.Operator op = ((AST.BuiltInOperator)lhs).Operator; op.RightArgument = BuildMonadic(symbol, rhs); node = op; } else { switch (symbol.Type) { case Tokens.DO: node = AST.Node.DyadicDo(lhs, rhs); break; case Tokens.RESULT: // Tokens.Assign AssignmentPreprocessor(lhs); node = AST.Node.Assign(lhs, rhs); break; default: if (rhs is AST.ExpressionList) { throw new ParseException("Incorrect call format", false); } node = AST.Node.DyadicFunction(symbol, lhs, rhs); break; } } return(node); }
/// <summary> /// Updates the given <see cref="AST.UserDefInvoke"/> node with the given <paramref name="argument"/> information. /// </summary> /// <param name="function">The <see cref="AST.UserDefInvoke"/> to update.</param> /// <param name="argument">The argument(s) to use for the node update.</param> /// <returns>The updated <see cref="AST.UserDefInvoke"/> node.</returns> private AST.UserDefInvoke UpdateUserDefInvoke(AST.UserDefInvoke function, AST.Node argument) { if (argument is AST.ExpressionList) { AST.ExpressionList arguments = (AST.ExpressionList)argument; foreach (AST.Node node in arguments.Items) { function.Arguments.AddLast(node); } } else { function.Arguments.AddLast(argument); } return(function); }
/// <summary> /// Retrieves the string format of the identifier list from left to right, leaving out any symbols after the last identifier. /// Given: A.B() /// Return: "A.B" /// Given: A.B.C()[0] /// Return: "A.B.C" /// Given: A.B().C /// Return: "A.B" /// Given: A.B[0].C /// Return: "A.B[0].C" /// </summary> /// <param name="identList"></param> /// <returns></returns> public static string GetIdentifierStringUntilFirstParenthesis(AST.Node node) { dynamic identList = node as IdentifierListNode; if (identList == null) { identList = node as AST.ImperativeAST.IdentifierListNode; } Validity.Assert(null != identList); string identListString = identList.ToString(); int removeIndex = identListString.IndexOf('('); if (removeIndex > 0) { identListString = identListString.Remove(removeIndex); } return(identListString); }
/// <summary> /// A selection statement is a block whose scope is a strict subset /// of the scope of its enclosing block. /// /// The controlling expression of an if statement shall have scalar type. /// </summary> /// <param name="env"></param> /// <returns></returns> public override AST.Node ToAST(Env env) { env.PushBlockScope(); AST.Expr e = expr.ToASTExpr(env); if (!e.Type.IsScalar) { throw new ETypeError(Pos, string.Format("expecting scalar type, given {0}", e.Type)); } AST.Node t = then.ToAST(env); AST.Node o = other != null?other.ToAST(env) : null; env.PopScope(); var labels = env.AllocIfLabel(); return(new AST.If(e, t, o, labels.Item1, labels.Item2)); }
private AST.Node BuildMonadic(AST.Token symbol, AST.Node argument) { AST.Node node; if (symbol.Type == Tokens.DO) { node = AST.Node.MonadicDo(argument); } else if (argument is AST.ExpressionList) { node = AST.Node.BuiltinInvoke(symbol, (AST.ExpressionList)argument); } else { node = AST.Node.MonadicFunction(symbol, argument); } return(node); }
private void BuildVariableUsages( AST.Node node, AST.FunctionDeclaration parent, IDictionary <AST.VariableDeclaration, HashSet <AST.FunctionDeclaration> > result) { var newParent = parent; switch (node) { case AST.FunctionDeclaration declaration: { newParent = declaration; break; } case AST.VariableDeclaration declaration: { if (!result.ContainsKey(declaration)) { result.Add(declaration, new HashSet <AST.FunctionDeclaration>()); } result[declaration].Add(parent); break; } case AST.Variable variable: { if (!result.ContainsKey(variable.Declaration)) { result.Add(variable.Declaration, new HashSet <AST.FunctionDeclaration>()); } result[variable.Declaration].Add(parent); break; } } foreach (var child in node.Children()) { this.BuildVariableUsages(child, newParent, result); } }
/// <summary> /// Builds the final AST for the specified SPPF node reference /// </summary> /// <param name="reference">A reference to an SPPF node in a specific version</param> /// <returns>The AST node for the SPPF reference</returns> public AST.Node BuildFinalAST(SPPFNodeRef reference) { SPPFNode sppfNode = sppf.GetNode(reference.NodeId); SPPFNodeVersion version = (sppfNode as SPPFNodeNormal).GetVersion(reference.Version); if (version.ChildrenCount == 0) { return(new AST.Node(version.Label)); } AST.Node[] buffer = new AST.Node[version.ChildrenCount]; for (int i = 0; i != version.ChildrenCount; i++) { buffer[i] = BuildFinalAST(version.Children[i]); } int first = result.Store(buffer, 0, version.ChildrenCount); return(new AST.Node(version.Label, version.ChildrenCount, first)); }
int GetDIFile(AST.Node node) { if (!debugInfoFileLookup.TryGetValue(node.token.filename, out int fileIdx)) { var fn = Backend.EscapeString(System.IO.Path.GetFileName(node.token.filename)); var dir = Backend.EscapeString(System.IO.Path.GetDirectoryName(node.token.filename)); string checksum; using (var md5 = System.Security.Cryptography.MD5.Create()) { using (var stream = File.OpenRead(node.token.filename)) { checksum = ByteArrayToString(md5.ComputeHash(stream)); } } var nodeString = $"!DIFile(filename: \"{fn}\", directory: \"{dir}\", checksumkind: CSK_MD5, checksum: \"{checksum}\")"; fileIdx = AddDebugInfoNode(nodeString); debugInfoFileLookup.Add(node.token.filename, fileIdx); } return(fileIdx); }
public override AST.Node ToAST(Env env) { /// The controlling expression shall have integer type. e = expr.ToASTExpr(env); if (!e.Type.IsInteger && e.Type.Kind != TKind.ENUM) { throw new ETypeError(Pos, "the controlling expression of switch statement shall have integer type"); } /// Integer promotions are performed on the controlling expression. e = e.IntPromote(); env.PushSwitch(this); /// Semantic check the statment. AST.Node s = stmt.ToAST(env); env.PopBreakable(); return(new AST.Switch(breakLabel, cases, defaultLabel, e, s)); }
int GetDIScope(AST.Node scopeRoot) { int scopeIdx = -1; if (scopeRoot != null && !debugInfoScopeLookup.TryGetValue(scopeRoot, out scopeIdx)) { switch (scopeRoot) { case AST.ProgramRoot programRoot: scopeIdx = GetDICompileUnit(programRoot); break; case AST.FunctionDefinition fun: scopeIdx = GetDISubprogram(fun); break; case AST.Block block: if (block.parent is AST.FunctionDefinition fd) { scopeIdx = GetDISubprogram(fd); } else { scopeIdx = GetDILexicalBlock(block); } break; case AST.Module ns: // TODO(pragma): NAMESPACES scopeIdx = GetDIScope(debugRootNode); break; default: scopeIdx = -1; break; } } return(scopeIdx); }
private void TraverseTree( AST.Node node, IReadOnlyDictionary <AST.VariableDeclaration, HashSet <AST.FunctionDeclaration> > variableUsages, Function parentFunction = null) { switch (node) { case AST.FunctionDeclaration functionDeclaration: { var function = FunctionBuilder.CreateFunction(functionDeclaration, parentFunction); functionDeclaration.Function = function; foreach (var argument in functionDeclaration.Parameters) { argument.IntermediateVariable = this.ReserveLocation(function, variableUsages, argument); } if (functionDeclaration.Body != null) { this.TraverseTree(functionDeclaration.Body, variableUsages, function); } return; } case AST.VariableDeclaration variableDeclaration: { variableDeclaration.IntermediateVariable = this.ReserveLocation(parentFunction, variableUsages, variableDeclaration); break; } } foreach (var child in node.Children()) { this.TraverseTree(child, variableUsages, parentFunction); } }
public override AST.Node ToAST(Env env) { /// Check the switch statement. Switch sw = env.GetSwitch(); if (sw == null) { throw new Error(Pos, "default statement not in switch statement"); } /// At most one default statement in a switch. if (sw.defaultLabel != null) { throw new Error(Pos, "at most one default label in a switch statement"); } string label = env.AllocDefaultLabel(); sw.defaultLabel = label; AST.Node s = stmt.ToAST(env); return(new AST.Labeled(label, s)); }
/// <summary> /// Sets the content of the i-th item /// </summary> /// <param name="index">The index of the item to set</param> /// <param name="symbol">The symbol</param> /// <param name="action">The tree action</param> public void SetAt(int index, TableElemRef symbol, TreeAction action) { nodes[index] = new AST.Node(symbol); actions[index] = action; }
private void SetupUserDefFunction() { this.isfunction = true; this.function = null; this.variables = new Variables(); }
private void TearDownUserDefFunction() { this.isfunction = false; this.function = null; this.variables = null; }
public ScanObj(int t, AST.Node val, LexLocation loc) { this.token = t; this.yylval = val; this.yylloc = loc; }
/// <summary> /// Initializes paren expression. /// </summary> internal ParenExpr(AST.Node expr) { Debug.Assert(expr != null, "expr != null"); _expr = expr; }
public UserFunctionResolver(List <string> parameters, AST.Node function, SymbolTable table) { this.call = function; this.symTable = table; paramList = parameters; }
/// <summary> /// Finalizes the parse tree and returns it /// </summary> /// <param name="root">The identifier of the SPPF node that serves as root</param> /// <returns>The final parse tree</returns> public AST GetTree(int root) { AST.Node astRoot = BuildFinalAST(new SPPFNodeRef(root, 0)); result.StoreRoot(astRoot); return(result); }
virtual public void visit(AST.Node node) { throw new NotImplementedException(); }
/// <summary> /// Initializes the root of this sub-tree /// </summary> /// <param name="symbol">The root's symbol</param> /// <param name="action">The tree action applied on the root</param> public void SetupRoot(TableElemRef symbol, TreeAction action) { nodes[0] = new AST.Node(symbol); actions[0] = action; }
public static MonkeyObject Eval(AST.Node node, Object.Environment environment) { MonkeyObject left; MonkeyObject index; MonkeyObject val; switch (node) { case AST.Program p: return(evalProgram(p, environment)); case AST.BlockStatement bs: return(evalBlockStatement(bs, environment)); case AST.ExpressionStatement xs: return(Eval(xs.Expression, environment)); case AST.LetStatement ls: val = Eval(ls.Value, environment); if (val?.Type == MonkeyObjectType.ERROR) { return(val); } environment.Set(ls.Name.Value, val); break; case AST.ReturnStatement rs: val = Eval(rs.ReturnValue, environment); if (val?.Type == MonkeyObjectType.ERROR) { return(val); } return(new MonkeyReturnValue { Value = val }); case AST.HashLiteral hl: return(evalHashLiteral(hl, environment)); case AST.ArrayLiteral al: var elements = evalExpressions(al.Elements, environment); if (elements.Count == 1 && elements[0]?.Type == MonkeyObjectType.ERROR) { return(elements[0]); } return(new MonkeyArray { Elements = elements }); case AST.FunctionLiteral fl: return(new Object.Function { Parameters = fl.Parameters, Env = environment, Body = fl.Body }); case AST.IfExpression ifx: return(evalIfExpression(ifx, environment)); case AST.CallExpression cl: var function = Eval(cl.Function, environment); if (function?.Type == MonkeyObjectType.ERROR) { return(function); } var args = evalExpressions(cl.Arguments, environment); if (args.Count == 1 && args[0]?.Type == MonkeyObjectType.ERROR) { return(args[0]); } return(applyFunction(function, args)); case AST.InfixExpression ix: left = Eval(ix.Left, environment); if (left?.Type == MonkeyObjectType.ERROR) { return(left); } index = Eval(ix.Right, environment); if (index?.Type == MonkeyObjectType.ERROR) { return(index); } return(evalInfixExpression(ix.Op, left, index)); case AST.PrefixExpression px: index = Eval(px.Right, environment); if (index?.Type == MonkeyObjectType.ERROR) { return(index); } return(evalPrefixExpression(px.Op, index)); case AST.IndexExpression idx: left = Eval(idx.Left, environment); if (left?.Type == MonkeyObjectType.ERROR) { return(left); } index = Eval(idx.Index, environment); if (index?.Type == MonkeyObjectType.ERROR) { return(index); } return(evalIndexExpression(left, index)); case AST.IntegerLiteral il: return(new MonkeyInteger { Value = il.Value }); case AST.BooleanExpression b: return(nativeBoolToMonkeyBoolean(b.Value)); case AST.Identifier id: return(evalIdentifier(id, environment)); case AST.StringLiteral sl: return(new MonkeyString { Value = sl.Value }); } return(null); }