public override AST.Node ToAST(Env env) { /// An iteration statement is a block. env.PushBlockScope(); /// The controlling expression should have scalar type. AST.Expr e = expr.ToASTExpr(env); if (!e.Type.IsScalar) { throw new ETypeError(Pos, "the controlling expression of iteration statement should have scalar type"); } /// The loop body is also a block. env.PushBlockScope(); /// Add this loop to the environemnt. env.PushLoop(this); var b = body.ToASTCompoundStmt(env); env.PopBreakable(); env.PopScope(); env.PopScope(); return(new AST.While(breakLabel, continueLabel, secondPlusLabel, firstLabel, e, b)); }
public override AST.Node ToAST(Env env) { /// An iteration statement is a block. env.PushBlockScope(); /// Check the expressions. /// An omitted expression-2 is replaced by a nonzero constant. var i = initExpr != null?initExpr.ToAST(env) : (initDecl != null ? initDecl.ToAST(env) : null); var p = pred != null?pred.ToASTExpr(env) : new AST.ConstIntExpr(TInt.Instance, 1, env.ASTEnv); var q = iter != null?iter.ToAST(env) : null; /// The controlling expression of a iteration statement shall have scalar type. if (!p.Type.IsScalar) { throw new ETypeError(Pos, "the controlling expression of iteration statement should have scalar type"); } /// Add this loop to the environment. env.PushLoop(this); var b = body.ToASTCompoundStmt(env); env.PopBreakable(); env.PopScope(); return(new AST.For(breakLabel, continueLabel, secondPlusLabel, firstLabel, i, p, q, b)); }
public override AST.Node ToAST(Env env) { env.PushBlockScope(); env.PushBlockScope(); env.PushLoop(this); var b = body.ToASTCompoundStmt(env); env.PopBreakable(); env.PopScope(); AST.Expr e = expr.ToASTExpr(env); if (!e.Type.IsScalar) { throw new ETypeError(Pos, "the controlling expression of iteration statement should be have scalar type"); } env.PopScope(); return(new AST.Do(breakLabel, continueLabel, secondPlusLabel, firstLabel, e, b)); }
public AST.CompoundStmt ToASTCompoundStmt(Env env) { env.PushBlockScope(); LinkedList <AST.Node> results = new LinkedList <AST.Node>(); foreach (var stmt in stmts) { results.AddLast(stmt.ToAST(env)); } env.PopScope(); return(new AST.CompoundStmt(results)); }
/// <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)); }
public override AST.Node ToAST(Env env) { T baseType = specifiers.GetT(env); var result = declarator.Declare(env, baseType); if (declarations != null) { throw new Error(Pos, "sorry we donot support old-style function definition"); } /// The identifier declared in a function definition (which is the name of the function) shall /// have a function type if (!result.Item2.IsFunc) { throw new ETypeError(Pos, "function definition should have function type"); } /// The storage-class specifier, if any, shall be either extern or static. if (specifiers.storage != StoreSpec.Kind.EXTERN && specifiers.storage != StoreSpec.Kind.NONE && specifiers.storage != StoreSpec.Kind.STATIC) { throw new Error(Pos, string.Format("illegal storage specifier {0} in function definition", specifiers.storage)); } /// Determine the linkage. var link = specifiers.storage == StoreSpec.Kind.STATIC ? SymbolEntry.Link.INTERNAL : SymbolEntry.Link.EXTERNAL; var entry = env.GetSymbol(result.Item1); if (entry == null) { /// This identifier has not been used. env.AddFunc(result.Item1, result.Item2, link, Pos); } else { /// This identifier has been declared. /// Check if it's a function type. if (!entry.type.Equals(result.Item2)) { throw new ERedefineSymbolTypeConflict(Pos, result.Item1, entry.type, result.Item2); } /// Check if the function has already been defined. if (entry.type.IsDefined) { throw new ERedefineFunction(Pos, result.Item1); } /// Define the function. entry.type.DefFunc(); } TFunc type = result.Item2.nake as TFunc; /// Push a new scope. env.PushFuncScope(result.Item1, type, result.Item3, Pos); /// Semantic check the function body. AST.CompoundStmt b = body.ToASTCompoundStmt(env); string returnLabel = env.GetReturnLabel(); env.PopScope(); return(new AST.FuncDef( result.Item1, returnLabel, type, result.Item3, b, env.ASTEnv, specifiers.storage != StoreSpec.Kind.STATIC )); }