diff options
-rw-r--r-- | ll.cpp | 129 |
1 files changed, 40 insertions, 89 deletions
@@ -245,14 +245,9 @@ static AST* parseIfExpr(const SExp& exp) list<SExp>::const_iterator i = exp.list.begin(); ++i; - AST* cond = parseExpression(*i++); - if (!cond) return 0; - - AST* then = parseExpression(*i++); - if (!then) return 0; - + AST* cond = parseExpression(*i++); + AST* then = parseExpression(*i++); AST* otherwise = parseExpression(*i++); - if (!otherwise) return 0; return new ASTIf(cond, then, otherwise); } @@ -266,10 +261,7 @@ static AST* parseCallExpr(const SExp& exp) vector<AST*> params; for (++i; i != exp.list.end(); ++i) - if (AST* p = parseExpression(*i)) - params.push_back(p); - else - return 0; + params.push_back(parseExpression(*i)); return new ASTCall(name, params); } @@ -299,12 +291,9 @@ static ASTFunction* parseDefinition(const SExp& exp) ++i; ASTPrototype* proto = ParsePrototype(false, *i++); - if (proto == 0) return 0; - - if (AST* body = parseExpression(*i++)) - return new ASTFunction(proto, body); - - return 0; + AST* body = parseExpression(*i++); + + return new ASTFunction(proto, body); } /// foreign ::= ("foreign" prototype expression) @@ -321,9 +310,7 @@ static AST* parseExpression(const SExp& exp) { if (exp.type == SExp::LIST) { const string& form = head(exp); - if (exp.list.empty()) { - return NULL; - } else if (form == "if") { + if (form == "if") { return parseIfExpr(exp); } else if (form == "def") { return parseDefinition(exp); @@ -337,7 +324,7 @@ static AST* parseExpression(const SExp& exp) } else if (isdigit(exp.atom[0])) { return parseNumberExpr(exp); } else { - return NULL; + throw SyntaxError("Illegal atom"); } } @@ -383,29 +370,21 @@ Value* ASTNumber::Codegen(CEnv& cenv) Value* ASTVariable::Codegen(CEnv& cenv) { - // Look this variable up in the function. map<string, Value*>::const_iterator v = cenv.env.find(_name); - if (v != cenv.env.end()) - return v->second; - else - return ErrorV("Unknown variable name"); + if (v == cenv.env.end()) throw SyntaxError("Undefined identifier"); + return v->second; } Value* ASTCall::Codegen(CEnv& cenv) { // Look up the name in the global module table. Function* f = cenv.module->getFunction(_func); - if (f == 0) - return ErrorV("Unknown function referenced"); - - if (f->arg_size() != _args.size()) - return ErrorV("Incorrect # arguments passed"); + if (f == 0) throw SyntaxError("Undefined function"); + if (f->arg_size() != _args.size()) throw SyntaxError("Illegal arguments"); vector<Value*> args; - for (size_t i = 0, e = _args.size(); i != e; ++i) { + for (size_t i = 0, e = _args.size(); i != e; ++i) args.push_back(_args[i]->Codegen(cenv)); - if (args.back() == 0) return 0; - } return cenv.builder.CreateCall(f, args.begin(), args.end(), "calltmp"); } @@ -413,7 +392,6 @@ Value* ASTCall::Codegen(CEnv& cenv) Value* ASTIf::Codegen(CEnv& cenv) { Value* condV = _cond->Codegen(cenv); - if (condV == 0) return 0; // Convert condition to a bool by comparing equal to 0.0. condV = cenv.builder.CreateFCmpONE( @@ -433,7 +411,6 @@ Value* ASTIf::Codegen(CEnv& cenv) cenv.builder.SetInsertPoint(thenBB); Value* thenV = _then->Codegen(cenv); - if (thenV == 0) return 0; cenv.builder.CreateBr(mergeBB); // Codegen of 'Then' can change the current block, update thenBB @@ -444,7 +421,6 @@ Value* ASTIf::Codegen(CEnv& cenv) cenv.builder.SetInsertPoint(elseBB); Value* elseV = _else->Codegen(cenv); - if (elseV == 0) return 0; cenv.builder.CreateBr(mergeBB); // Codegen of 'Else' can change the current block, update elseBB @@ -466,39 +442,35 @@ Function* ASTPrototype::Funcgen(CEnv& cenv) vector<const Type*> Doubles(_args.size(), Type::DoubleTy); FunctionType* FT = FunctionType::get(Type::DoubleTy, Doubles, false); - Function* F = Function::Create(FT, Function::ExternalLinkage, _name, cenv.module); + Function* f = Function::Create( + FT, Function::ExternalLinkage, _name, cenv.module); // If F conflicted, there was already something named 'Name'. // If it has a body, don't allow redefinition. - if (F->getName() != _name) { + if (f->getName() != _name) { // Delete the one we just made and get the existing one. - F->eraseFromParent(); - F = cenv.module->getFunction(_name); + f->eraseFromParent(); + f = cenv.module->getFunction(_name); // If F already has a body, reject this. - if (!F->empty()) { - ErrorF(string("Redefinition of function '").append(_name).append("'").c_str()); - return 0; - } + if (!f->empty()) throw SyntaxError("Function redefined"); // If F took a different number of args, reject. - if (F->arg_size() != _args.size()) { - ErrorF("Redefinition of function with different # args"); - return 0; - } + if (f->arg_size() != _args.size()) + throw SyntaxError("Function redefined with mismatched arguments"); } // Set names for all arguments. - unsigned Idx = 0; - for (Function::arg_iterator AI = F->arg_begin(); Idx != _args.size(); - ++AI, ++Idx) { - AI->setName(_args[Idx]); + size_t i = 0; + for (Function::arg_iterator a = f->arg_begin(); i != _args.size(); + ++a, ++i) { + a->setName(_args[i]); // Add arguments to variable symbol table. - cenv.env[_args[Idx]] = AI; + cenv.env[_args[i]] = a; } - return F; + return f; } Function* ASTFunction::Funcgen(CEnv& cenv) @@ -506,29 +478,23 @@ Function* ASTFunction::Funcgen(CEnv& cenv) cenv.env.clear(); Function* f = _proto->Funcgen(cenv); - if (f == 0) - return 0; // Create a new basic block to start insertion into. BasicBlock* bb = BasicBlock::Create("entry", f); cenv.builder.SetInsertPoint(bb); - if (Value* retVal = _body->Codegen(cenv)) { - // Finish off the function. - cenv.builder.CreateRet(retVal); - - // Validate the generated code, checking for consistency. - verifyFunction(*f); - - // Optimize the function. - cenv.fpm.run(*f); - + try { + Value* retVal = _body->Codegen(cenv); + cenv.builder.CreateRet(retVal); // Finish function + verifyFunction(*f); // Validate generated code + cenv.fpm.run(*f); // Optimize function return f; + } catch (std::exception e) { + f->eraseFromParent(); // Error reading body, remove function + throw e; } - // Error reading body, remove function. - f->eraseFromParent(); - return 0; + return 0; // Never reached } @@ -544,7 +510,8 @@ static void repl(CEnv& cenv, ExecutionEngine* engine) std::cout.flush(); SExp exp = readExpression(std::cin); - if (AST* ast = parseExpression(exp)) { + try { + AST* ast = parseExpression(exp); if (ast->evaluatable()) { ASTPrototype* proto = new ASTPrototype(false, "", vector<string>()); ASTFunction* func = new ASTFunction(proto, ast); @@ -557,30 +524,14 @@ static void repl(CEnv& cenv, ExecutionEngine* engine) std::cout << "Generated code:" << endl; code->dump(); } - } else { - break; + } catch (SyntaxError e) { + std::cerr << "Syntax error: " << e.what() << endl; } } } /*************************************************************************** - * "Library" functions that can be "extern'd" from user code. * - ***************************************************************************/ - -extern "C" { - -double -putchard(double X) -{ - putchar((char)X); - return 0; -} - -} // extern "C" - - -/*************************************************************************** * Main driver code. ***************************************************************************/ |