Commit 98c5b35993332c80acfbb1f877deecb93afb3091
1 parent
e3f7f8a769
Exists in
master
added irgen to node and the basic emit messages in stmt, only missing for,while,if
Showing 5 changed files with 146 additions and 41 deletions Inline Diff
CMakeLists.txt
View file @
98c5b35
File was created | 1 | cmake_minimum_required(VERSION 3.5) | ||
2 | project(cse_131pa4) | |||
3 | ||||
4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | |||
5 | ||||
6 | set(SOURCE_FILES | |||
7 | ast.cc | |||
8 | ast.h | |||
9 | ast_decl.cc | |||
10 | ast_decl.h | |||
11 | ast_expr.cc | |||
12 | ast_expr.h | |||
13 | ast_stmt.cc | |||
14 | ast_stmt.h | |||
15 | ast_type.cc | |||
16 | ast_type.h | |||
17 | errors.cc | |||
18 | errors.h | |||
19 | irgen.cc | |||
20 | irgen.h | |||
21 | list.h | |||
22 | location.h | |||
23 | main.cc | |||
24 | parser.h | |||
25 | scanner.h | |||
26 | symtable.cc | |||
27 | symtable.h | |||
28 | utility.cc |
ast.cc
View file @
98c5b35
/* File: ast.cc | 1 | 1 | /* File: ast.cc | |
* ------------ | 2 | 2 | * ------------ | |
*/ | 3 | 3 | */ | |
4 | 4 | |||
#include "ast.h" | 5 | 5 | #include "ast.h" | |
#include "ast_type.h" | 6 | 6 | #include "ast_type.h" | |
#include "ast_decl.h" | 7 | 7 | #include "ast_decl.h" | |
#include "symtable.h" | 8 | 8 | #include "symtable.h" | |
#include <string.h> // strdup | 9 | 9 | #include <string.h> // strdup | |
#include <stdio.h> // printf | 10 | 10 | #include <stdio.h> // printf | |
11 | 11 | |||
12 | 12 | |||
Node::Node(yyltype loc) { | 13 | 13 | Node::Node(yyltype loc) { | |
location = new yyltype(loc); | 14 | 14 | location = new yyltype(loc); | |
parent = NULL; | 15 | 15 | parent = NULL; | |
} | 16 | 16 | } | |
17 | 17 | |||
Node::Node() { | 18 | 18 | Node::Node() { | |
location = NULL; | 19 | 19 | location = NULL; | |
parent = NULL; | 20 | 20 | parent = NULL; | |
} | 21 | 21 | } | |
22 | 22 | |||
/* The Print method is used to print the parse tree nodes. | 23 | 23 | /* The Print method is used to print the parse tree nodes. | |
* If this node has a location (most nodes do, but some do not), it | 24 | 24 | * If this node has a location (most nodes do, but some do not), it | |
* will first print the line number to help you match the parse tree | 25 | 25 | * will first print the line number to help you match the parse tree | |
* back to the source text. It then indents the proper number of levels | 26 | 26 | * back to the source text. It then indents the proper number of levels | |
* and prints the "print name" of the node. It then will invoke the | 27 | 27 | * and prints the "print name" of the node. It then will invoke the | |
* virtual function PrintChildren which is expected to print the | 28 | 28 | * virtual function PrintChildren which is expected to print the | |
* internals of the node (itself & children) as appropriate. | 29 | 29 | * internals of the node (itself & children) as appropriate. | |
*/ | 30 | 30 | */ | |
void Node::Print(int indentLevel, const char *label) { | 31 | 31 | void Node::Print(int indentLevel, const char *label) { | |
const int numSpaces = 3; | 32 | 32 | const int numSpaces = 3; | |
printf("\n"); | 33 | 33 | printf("\n"); | |
if (GetLocation()) | 34 | 34 | if (GetLocation()) | |
printf("%*d", numSpaces, GetLocation()->first_line); | 35 | 35 | printf("%*d", numSpaces, GetLocation()->first_line); | |
else | 36 | 36 | else | |
printf("%*s", numSpaces, ""); | 37 | 37 | printf("%*s", numSpaces, ""); | |
printf("%*s%s%s: ", indentLevel*numSpaces, "", | 38 | 38 | printf("%*s%s%s: ", indentLevel*numSpaces, "", | |
label? label : "", GetPrintNameForNode()); | 39 | 39 | label? label : "", GetPrintNameForNode()); | |
PrintChildren(indentLevel); | 40 | 40 | PrintChildren(indentLevel); | |
} | 41 | 41 | } | |
42 | 42 | |||
Identifier::Identifier(yyltype loc, const char *n) : Node(loc) { | 43 | 43 | Identifier::Identifier(yyltype loc, const char *n) : Node(loc) { | |
name = strdup(n); | 44 | 44 | name = strdup(n); | |
} | 45 | 45 | } | |
46 | 46 | |||
void Identifier::PrintChildren(int indentLevel) { | 47 | 47 | void Identifier::PrintChildren(int indentLevel) { | |
printf("%s", name); | 48 | 48 | printf("%s", name); | |
} | 49 | 49 | } | |
50 | 50 | |||
/*------------------------------------------------------------------------------------ | 51 | 51 | /*------------------------------------------------------------------------------------ | |
* Symbol Table Information | 52 | 52 | * Symbol Table Information | |
*----------------------------------------------------------------------------------*/ | 53 | 53 | *----------------------------------------------------------------------------------*/ | |
SymbolTable symbols; | 54 | |||
55 | ||||
pair<Decl*,llvm::Value *> findSymbol(string s) { | 56 | 54 | pair<Decl*,llvm::Value *> findSymbol(string s) { | |
for(int i = symbols.size() - 1; i >= 0; i--) { | 57 | 55 | for(int i = symbols.size() - 1; i >= 0; i--) { | |
if(symbols[i].count(s) > 0) return symbols[i][s]; | 58 | 56 | if(symbols[i].count(s) > 0) return symbols[i][s]; | |
} | 59 | 57 | } | |
return make_pair<Decl*,llvm::Value *>(NULL,NULL); | 60 | 58 | return make_pair<Decl*,llvm::Value *>(NULL,NULL); | |
} | 61 | 59 | } | |
62 | 60 | |||
pair<Decl*,llvm::Value *> findSymbol(Decl* d) { | 63 | 61 | pair<Decl*,llvm::Value *> findSymbol(Decl* d) { | |
string s(d->GetIdentifier()->GetName()); | 64 | 62 | string s(d->GetIdentifier()->GetName()); | |
return findSymbol(s); | 65 | 63 | return findSymbol(s); | |
} | 66 | 64 | } | |
67 | 65 | |||
bool isInCurrentScope(string s) { | 68 | 66 | bool isInCurrentScope(string s) { | |
if(symbols.size() == 0) return false; | 69 | 67 | if(symbols.size() == 0) return false; | |
return symbols[symbols.size()-1].count(s); | 70 | 68 | return symbols[symbols.size()-1].count(s); | |
} | 71 | 69 | } | |
72 | 70 | |||
bool isInCurrentScope(Decl* d) { | 73 | 71 | bool isInCurrentScope(Decl* d) { | |
string s(d->GetIdentifier()->GetName()); | 74 | 72 | string s(d->GetIdentifier()->GetName()); | |
return isInCurrentScope(s); | 75 | 73 | return isInCurrentScope(s); | |
} | 76 | 74 | } | |
77 | 75 | |||
bool isInScope(string s) { | 78 | 76 | bool isInScope(string s) { | |
pair<Decl*,llvm::Value *> tmp = findSymbol(s); | 79 | 77 | pair<Decl*, llvm::Value *> tmp = findSymbol(s); | |
return tmp.first != NULL; | 80 | 78 | return tmp.first != NULL; | |
} | 81 | 79 | } | |
82 | 80 | |||
bool isInScope(Decl* d) { | 83 | 81 | bool isInScope(Decl* d) { | |
string s(d->GetIdentifier()->GetName()); | 84 | 82 | string s(d->GetIdentifier()->GetName()); |
ast.h
View file @
98c5b35
/** | 1 | 1 | /** | |
* File: ast.h | 2 | 2 | * File: ast.h | |
* ----------- | 3 | 3 | * ----------- | |
* This file defines the abstract base class Node and the concrete | 4 | 4 | * This file defines the abstract base class Node and the concrete | |
* Identifier and Error node subclasses that are used through the tree as | 5 | 5 | * Identifier and Error node subclasses that are used through the tree as | |
* leaf nodes. A parse tree is a hierarchical collection of ast nodes (or, | 6 | 6 | * leaf nodes. A parse tree is a hierarchical collection of ast nodes (or, | |
* more correctly, of instances of concrete subclassses such as VarDecl, | 7 | 7 | * more correctly, of instances of concrete subclassses such as VarDecl, | |
* ForStmt, and AssignExpr). | 8 | 8 | * ForStmt, and AssignExpr). | |
* | 9 | 9 | * | |
* Location: Each node maintains its lexical location (line and columns in | 10 | 10 | * Location: Each node maintains its lexical location (line and columns in | |
* file), that location can be NULL for those nodes that don't care/use | 11 | 11 | * file), that location can be NULL for those nodes that don't care/use | |
* locations. The location is typcially set by the node constructor. The | 12 | 12 | * locations. The location is typcially set by the node constructor. The | |
* location is used to provide the context when reporting semantic errors. | 13 | 13 | * location is used to provide the context when reporting semantic errors. | |
* | 14 | 14 | * | |
* Parent: Each node has a pointer to its parent. For a Program node, the | 15 | 15 | * Parent: Each node has a pointer to its parent. For a Program node, the | |
* parent is NULL, for all other nodes it is the pointer to the node one level | 16 | 16 | * parent is NULL, for all other nodes it is the pointer to the node one level | |
* up in the parse tree. The parent is not set in the constructor (during a | 17 | 17 | * up in the parse tree. The parent is not set in the constructor (during a | |
* bottom-up parse we don't know the parent at the time of construction) but | 18 | 18 | * bottom-up parse we don't know the parent at the time of construction) but | |
* instead we wait until assigning the children into the parent node and then | 19 | 19 | * instead we wait until assigning the children into the parent node and then | |
* set up links in both directions. The parent link is typically not used | 20 | 20 | * set up links in both directions. The parent link is typically not used | |
* during parsing, but is more important in later phases. | 21 | 21 | * during parsing, but is more important in later phases. | |
* | 22 | 22 | * | |
* Printing: This functionaility is saved from pp2 of the node classes to | 23 | 23 | * Printing: This functionaility is saved from pp2 of the node classes to | |
* print out the AST tree for debugging purpose. Each node class is | 24 | 24 | * print out the AST tree for debugging purpose. Each node class is | |
* responsible for printing itself/children by overriding the virtual | 25 | 25 | * responsible for printing itself/children by overriding the virtual | |
* PrintChildren() and GetPrintNameForNode() methods. All the classes we | 26 | 26 | * PrintChildren() and GetPrintNameForNode() methods. All the classes we | |
* provide already implement these methods, so your job is to construct the | 27 | 27 | * provide already implement these methods, so your job is to construct the | |
* nodes and wire them up during parsing. Once that's done, printing is a snap! | 28 | 28 | * nodes and wire them up during parsing. Once that's done, printing is a snap! | |
29 | 29 | |||
* Semantic analysis: For pp3 you are adding "Check" behavior to the ast | 30 | 30 | * Semantic analysis: For pp3 you are adding "Check" behavior to the ast | |
* node classes. Your semantic analyzer should do an inorder walk on the | 31 | 31 | * node classes. Your semantic analyzer should do an inorder walk on the | |
* parse tree, and when visiting each node, verify the particular | 32 | 32 | * parse tree, and when visiting each node, verify the particular | |
* semantic rules that apply to that construct. | 33 | 33 | * semantic rules that apply to that construct. | |
34 | 34 | |||
*/ | 35 | 35 | */ | |
36 | 36 | |||
37 | #pragma clang diagnostic push | |||
38 | #pragma ide diagnostic ignored "CannotResolve" | |||
#ifndef _H_ast | 37 | 39 | #ifndef _H_ast | |
#define _H_ast | 38 | 40 | #define _H_ast | |
39 | 41 | |||
#include <stdlib.h> // for NULL | 40 | 42 | #include <stdlib.h> // for NULL | |
#include "irgen.h" | 41 | 43 | #include "irgen.h" | |
#include "location.h" | 42 | 44 | #include "location.h" | |
#include <iostream> | 43 | 45 | #include <iostream> | |
#include <vector> | 44 | 46 | #include <vector> | |
#include <map> | 45 | 47 | #include <map> | |
#include <algorithm> | 46 | 48 | #include <algorithm> | |
49 | //LLVM STUFF | |||
50 | #include "llvm/IR/Module.h" | |||
51 | #include "llvm/IR/LLVMContext.h" | |||
52 | #include "llvm/IR/Instructions.h" | |||
53 | #include "llvm/IR/Constants.h" | |||
47 | 54 | |||
using namespace std; | 48 | 55 | using namespace std; | |
49 | 56 | |||
class SymbolTable; | 50 | 57 | class SymbolTable; | |
class MyStack; | 51 | 58 | class MyStack; | |
class FnDecl; | 52 | 59 | class FnDecl; | |
class Decl; | 53 | 60 | class Decl; | |
54 | 61 | |||
class Node { | 55 | 62 | class Node { | |
protected: | 56 | 63 | protected: | |
yyltype *location; | 57 | 64 | yyltype *location; | |
Node *parent; | 58 | 65 | Node *parent; | |
59 | 66 | |||
public: | 60 | 67 | public: | |
Node(yyltype loc); | 61 | 68 | Node(yyltype loc); | |
Node(); | 62 | 69 | Node(); | |
70 | static IRGenerator * irGen; | |||
71 | SymbolTable symbols; | |||
virtual ~Node() {} | 63 | 72 | virtual ~Node() {} | |
64 | 73 | |||
yyltype *GetLocation() { return location; } | 65 | 74 | yyltype *GetLocation() { return location; } | |
void SetParent(Node *p) { parent = p; } | 66 | 75 | void SetParent(Node *p) { parent = p; } | |
Node *GetParent() { return parent; } | 67 | 76 | Node *GetParent() { return parent; } | |
68 | 77 | |||
virtual const char *GetPrintNameForNode() = 0; | 69 | 78 | virtual const char *GetPrintNameForNode() = 0; | |
70 | 79 | |||
// Print() is deliberately _not_ virtual | 71 | 80 | // Print() is deliberately _not_ virtual | |
// subclasses should override PrintChildren() instead | 72 | 81 | // subclasses should override PrintChildren() instead | |
void Print(int indentLevel, const char *label = NULL); | 73 | 82 | void Print(int indentLevel, const char *label = NULL); | |
virtual void PrintChildren(int indentLevel) {} | 74 | 83 | virtual void PrintChildren(int indentLevel) {} | |
75 | 84 | |||
virtual llvm::Value* Emit() { return NULL; } | 76 | 85 | virtual llvm::Value* Emit() { return NULL; } | |
}; | 77 | 86 | }; | |
78 | 87 | |||
79 | 88 | |||
class Identifier : public Node | 80 | 89 | class Identifier : public Node | |
{ | 81 | 90 | { | |
protected: | 82 | 91 | protected: | |
char *name; | 83 | 92 | char *name; | |
84 | 93 | |||
public: | 85 | 94 | public: | |
Identifier(yyltype loc, const char *name); | 86 | 95 | Identifier(yyltype loc, const char *name); | |
const char *GetPrintNameForNode() { return "Identifier"; } | 87 | 96 | const char *GetPrintNameForNode() { return "Identifier"; } | |
char *GetName() const { return name; } | 88 | 97 | char *GetName() const { return name; } | |
void PrintChildren(int indentLevel); | 89 | 98 | void PrintChildren(int indentLevel); | |
friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; } | 90 | 99 | friend ostream& operator<<(ostream& out, Identifier *id) { return out << id->name; } | |
}; | 91 | 100 | }; | |
92 | 101 | |||
93 | 102 | |||
// This node class is designed to represent a portion of the tree that | 94 | 103 | // This node class is designed to represent a portion of the tree that | |
// encountered syntax errors during parsing. The partial completed tree | 95 | 104 | // encountered syntax errors during parsing. The partial completed tree | |
// is discarded along with the states being popped, and an instance of | 96 | 105 | // is discarded along with the states being popped, and an instance of | |
// the Error class can stand in as the placeholder in the parse tree | 97 | 106 | // the Error class can stand in as the placeholder in the parse tree | |
// when your parser can continue after an error. | 98 | 107 | // when your parser can continue after an error. | |
class Error : public Node | 99 | 108 | class Error : public Node | |
{ | 100 | 109 | { | |
public: | 101 | 110 | public: | |
Error() : Node() {} | 102 | 111 | Error() : Node() {} | |
const char *GetPrintNameForNode() { return "Error"; } | 103 | 112 | const char *GetPrintNameForNode() { return "Error"; } | |
}; | 104 | 113 | }; | |
/*------------------------------------------------------------------------------------ | 105 | 114 | /*------------------------------------------------------------------------------------ | |
* Symbol Table Information | 106 | 115 | * Symbol Table Information | |
*----------------------------------------------------------------------------------*/ | 107 | 116 | *----------------------------------------------------------------------------------*/ |
ast_stmt.cc
View file @
98c5b35
/* File: ast_stmt.cc | 1 | 1 | /* File: ast_stmt.cc | |
* ----------------- | 2 | 2 | * ----------------- | |
* Implementation of statement node classes. | 3 | 3 | * Implementation of statement node classes. | |
*/ | 4 | 4 | */ | |
#include "ast_stmt.h" | 5 | 5 | #include "ast_stmt.h" | |
#include "ast_type.h" | 6 | 6 | #include "ast_type.h" | |
#include "ast_decl.h" | 7 | 7 | #include "ast_decl.h" | |
#include "ast_expr.h" | 8 | 8 | #include "ast_expr.h" | |
#include "symtable.h" | 9 | 9 | #include "symtable.h" | |
10 | 10 | |||
#include "irgen.h" | 11 | 11 | #include "irgen.h" | |
#include "llvm/Bitcode/ReaderWriter.h" | 12 | 12 | #include "llvm/Bitcode/ReaderWriter.h" | |
#include "llvm/Support/raw_ostream.h" | 13 | 13 | #include "llvm/Support/raw_ostream.h" | |
14 | 14 | |||
15 | 15 | |||
Program::Program(List<Decl*> *d) { | 16 | 16 | Program::Program(List<Decl*> *d) { | |
Assert(d != NULL); | 17 | 17 | Assert(d != NULL); | |
(decls=d)->SetParentAll(this); | 18 | 18 | (decls=d)->SetParentAll(this); | |
} | 19 | 19 | } | |
20 | 20 | |||
void Program::PrintChildren(int indentLevel) { | 21 | 21 | void Program::PrintChildren(int indentLevel) { | |
decls->PrintAll(indentLevel+1); | 22 | 22 | decls->PrintAll(indentLevel+1); | |
printf("\n"); | 23 | 23 | printf("\n"); | |
} | 24 | 24 | } | |
25 | 25 | //pls work | ||
llvm::Value* Program::Emit() { | 26 | 26 | llvm::Value* Program::Emit() { | |
// TODO: | 27 | 27 | llvm::Module *module = irGen->GetOrCreateModule("swag"); | |
// This is just a reference for you to get started | 28 | 28 | pushScope(); | |
// | 29 | 29 | for (int i = 0; i < decls->NumElements(); i++){ | |
// You can use this as a template and create Emit() function | 30 | 30 | decls->Nth(i)->Emit(); | |
// for individual node to fill in the module structure and instructions. | 31 | 31 | } | |
// | 32 | 32 | popScope(); | |
//IRGenerator irgen; | 33 | |||
llvm::Module *mod = irgen.GetOrCreateModule("Name_the_Module.bc"); | 34 | |||
35 | 33 | |||
// create a function signature | 36 | 34 | module->dump(); | |
std::vector<llvm::Type *> argTypes; | 37 | 35 | llvm::WriteBitcodeToFile(module, llvm::outs()); | |
llvm::Type *intTy = irgen.GetIntType(); | 38 | 36 | return NULL; | |
argTypes.push_back(intTy); | 39 | |||
llvm::ArrayRef<llvm::Type *> argArray(argTypes); | 40 | |||
llvm::FunctionType *funcTy = llvm::FunctionType::get(intTy, argArray, false); | 41 | |||
42 | ||||
// llvm::Function *f = llvm::cast<llvm::Function>(mod->getOrInsertFunction("foo", intTy, intTy, (Type *)0)); | 43 | |||
llvm::Function *f = llvm::cast<llvm::Function>(mod->getOrInsertFunction("Name_the_function", funcTy)); | 44 | |||
llvm::Argument *arg = f->arg_begin(); | 45 | |||
arg->setName("x"); | 46 | |||
47 | ||||
// insert a block into the runction | 48 | |||
llvm::LLVMContext *context = irgen.GetContext(); | 49 | |||
llvm::BasicBlock *bb = llvm::BasicBlock::Create(*context, "entry", f); | 50 | |||
51 | ||||
// create a return instruction | 52 | |||
llvm::Value *val = llvm::ConstantInt::get(intTy, 1); | 53 | |||
llvm::Value *sum = llvm::BinaryOperator::CreateAdd(arg, val, "", bb); | 54 | |||
llvm::ReturnInst::Create(*context, sum, bb); | 55 | |||
56 | ||||
// write the BC into standard output | 57 | |||
llvm::WriteBitcodeToFile(mod, llvm::outs()); | 58 | |||
} | 59 | 37 | } | |
60 | 38 | |||
StmtBlock::StmtBlock(List<VarDecl*> *d, List<Stmt*> *s) { | 61 | 39 | StmtBlock::StmtBlock(List<VarDecl*> *d, List<Stmt*> *s) { | |
Assert(d != NULL && s != NULL); | 62 | 40 | Assert(d != NULL && s != NULL); | |
(decls=d)->SetParentAll(this); | 63 | 41 | (decls=d)->SetParentAll(this); | |
(stmts=s)->SetParentAll(this); | 64 | 42 | (stmts=s)->SetParentAll(this); | |
} | 65 | 43 | } | |
66 | 44 | |||
void StmtBlock::PrintChildren(int indentLevel) { | 67 | 45 | void StmtBlock::PrintChildren(int indentLevel) { | |
decls->PrintAll(indentLevel+1); | 68 | 46 | decls->PrintAll(indentLevel+1); | |
stmts->PrintAll(indentLevel+1); | 69 | 47 | stmts->PrintAll(indentLevel+1); | |
} | 70 | 48 | } | |
71 | 49 | |||
DeclStmt::DeclStmt(Decl *d) { | 72 | 50 | DeclStmt::DeclStmt(Decl *d) { | |
Assert(d != NULL); | 73 | 51 | Assert(d != NULL); | |
(decl=d)->SetParent(this); | 74 | 52 | (decl=d)->SetParent(this); | |
} | 75 | 53 | } | |
76 | 54 | |||
void DeclStmt::PrintChildren(int indentLevel) { | 77 | 55 | void DeclStmt::PrintChildren(int indentLevel) { | |
decl->Print(indentLevel+1); | 78 | 56 | decl->Print(indentLevel+1); | |
} | 79 | 57 | } | |
80 | 58 | |||
ConditionalStmt::ConditionalStmt(Expr *t, Stmt *b) { | 81 | 59 | ConditionalStmt::ConditionalStmt(Expr *t, Stmt *b) { | |
Assert(t != NULL && b != NULL); | 82 | 60 | Assert(t != NULL && b != NULL); | |
(test=t)->SetParent(this); | 83 | 61 | (test=t)->SetParent(this); | |
(body=b)->SetParent(this); | 84 | 62 | (body=b)->SetParent(this); | |
} | 85 | 63 | } | |
86 | 64 | |||
ForStmt::ForStmt(Expr *i, Expr *t, Expr *s, Stmt *b): LoopStmt(t, b) { | 87 | 65 | ForStmt::ForStmt(Expr *i, Expr *t, Expr *s, Stmt *b): LoopStmt(t, b) { | |
Assert(i != NULL && t != NULL && b != NULL); | 88 | 66 | Assert(i != NULL && t != NULL && b != NULL); | |
(init=i)->SetParent(this); | 89 | 67 | (init=i)->SetParent(this); | |
step = s; | 90 | 68 | step = s; | |
if ( s ) | 91 | 69 | if ( s ) | |
(step=s)->SetParent(this); | 92 | 70 | (step=s)->SetParent(this); | |
} | 93 | 71 | } | |
94 | 72 | |||
void ForStmt::PrintChildren(int indentLevel) { | 95 | 73 | void ForStmt::PrintChildren(int indentLevel) { | |
init->Print(indentLevel+1, "(init) "); | 96 | 74 | init->Print(indentLevel+1, "(init) "); | |
test->Print(indentLevel+1, "(test) "); | 97 | 75 | test->Print(indentLevel+1, "(test) "); | |
if ( step ) | 98 | 76 | if ( step ) | |
step->Print(indentLevel+1, "(step) "); | 99 | 77 | step->Print(indentLevel+1, "(step) "); | |
body->Print(indentLevel+1, "(body) "); | 100 | 78 | body->Print(indentLevel+1, "(body) "); | |
} | 101 | 79 | } | |
102 | 80 | |||
void WhileStmt::PrintChildren(int indentLevel) { | 103 | 81 | void WhileStmt::PrintChildren(int indentLevel) { | |
test->Print(indentLevel+1, "(test) "); | 104 | 82 | test->Print(indentLevel+1, "(test) "); | |
body->Print(indentLevel+1, "(body) "); | 105 | 83 | body->Print(indentLevel+1, "(body) "); | |
} | 106 | 84 | } | |
107 | 85 | |||
IfStmt::IfStmt(Expr *t, Stmt *tb, Stmt *eb): ConditionalStmt(t, tb) { | 108 | 86 | IfStmt::IfStmt(Expr *t, Stmt *tb, Stmt *eb): ConditionalStmt(t, tb) { | |
Assert(t != NULL && tb != NULL); // else can be NULL | 109 | 87 | Assert(t != NULL && tb != NULL); // else can be NULL | |
elseBody = eb; | 110 | 88 | elseBody = eb; | |
if (elseBody) elseBody->SetParent(this); | 111 | 89 | if (elseBody) elseBody->SetParent(this); | |
} | 112 | 90 | } | |
113 | 91 | |||
void IfStmt::PrintChildren(int indentLevel) { | 114 | 92 | void IfStmt::PrintChildren(int indentLevel) { | |
if (test) test->Print(indentLevel+1, "(test) "); | 115 | 93 | if (test) test->Print(indentLevel+1, "(test) "); | |
if (body) body->Print(indentLevel+1, "(then) "); | 116 | 94 | if (body) body->Print(indentLevel+1, "(then) "); | |
if (elseBody) elseBody->Print(indentLevel+1, "(else) "); | 117 | 95 | if (elseBody) elseBody->Print(indentLevel+1, "(else) "); | |
} | 118 | 96 | } | |
119 | 97 | |||
120 | 98 | |||
ReturnStmt::ReturnStmt(yyltype loc, Expr *e) : Stmt(loc) { | 121 | 99 | ReturnStmt::ReturnStmt(yyltype loc, Expr *e) : Stmt(loc) { | |
expr = e; | 122 | 100 | expr = e; | |
if (e != NULL) expr->SetParent(this); | 123 | 101 | if (e != NULL) expr->SetParent(this); | |
} | 124 | 102 | } | |
125 | 103 | |||
void ReturnStmt::PrintChildren(int indentLevel) { | 126 | 104 | void ReturnStmt::PrintChildren(int indentLevel) { | |
if ( expr ) | 127 | 105 | if ( expr ) | |
expr->Print(indentLevel+1); | 128 | 106 | expr->Print(indentLevel+1); | |
} | 129 | 107 | } | |
130 | 108 | |||
SwitchLabel::SwitchLabel(Expr *l, Stmt *s) { | 131 | 109 | SwitchLabel::SwitchLabel(Expr *l, Stmt *s) { | |
Assert(l != NULL && s != NULL); | 132 | 110 | Assert(l != NULL && s != NULL); | |
(label=l)->SetParent(this); | 133 | 111 | (label=l)->SetParent(this); | |
(stmt=s)->SetParent(this); | 134 | 112 | (stmt=s)->SetParent(this); | |
} | 135 | 113 | } | |
136 | 114 | |||
SwitchLabel::SwitchLabel(Stmt *s) { | 137 | 115 | SwitchLabel::SwitchLabel(Stmt *s) { | |
Assert(s != NULL); | 138 | 116 | Assert(s != NULL); | |
label = NULL; | 139 | 117 | label = NULL; | |
(stmt=s)->SetParent(this); | 140 | 118 | (stmt=s)->SetParent(this); | |
} | 141 | 119 | } | |
142 | 120 | |||
void SwitchLabel::PrintChildren(int indentLevel) { | 143 | 121 | void SwitchLabel::PrintChildren(int indentLevel) { | |
if (label) label->Print(indentLevel+1); | 144 | 122 | if (label) label->Print(indentLevel+1); | |
if (stmt) stmt->Print(indentLevel+1); | 145 | 123 | if (stmt) stmt->Print(indentLevel+1); | |
} | 146 | 124 | } | |
147 | 125 | |||
SwitchStmt::SwitchStmt(Expr *e, List<Stmt *> *c, Default *d) { | 148 | 126 | SwitchStmt::SwitchStmt(Expr *e, List<Stmt *> *c, Default *d) { | |
Assert(e != NULL && c != NULL && c->NumElements() != 0 ); | 149 | 127 | Assert(e != NULL && c != NULL && c->NumElements() != 0 ); | |
(expr=e)->SetParent(this); | 150 | 128 | (expr=e)->SetParent(this); | |
(cases=c)->SetParentAll(this); | 151 | 129 | (cases=c)->SetParentAll(this); | |
def = d; | 152 | 130 | def = d; | |
if (def) def->SetParent(this); | 153 | 131 | if (def) def->SetParent(this); | |
} | 154 | 132 | } | |
155 | 133 | |||
void SwitchStmt::PrintChildren(int indentLevel) { | 156 | 134 | void SwitchStmt::PrintChildren(int indentLevel) { | |
if (expr) expr->Print(indentLevel+1); | 157 | 135 | if (expr) expr->Print(indentLevel+1); | |
if (cases) cases->PrintAll(indentLevel+1); | 158 | 136 | if (cases) cases->PrintAll(indentLevel+1); | |
if (def) def->Print(indentLevel+1); | 159 | 137 | if (def) def->Print(indentLevel+1); | |
138 | } | |||
139 | ||||
140 | //rest of the emits | |||
141 | llvm::Value * StmtBlock::Emit(){ | |||
142 | pushScope(); | |||
143 | for (int i = 0; i < decls->NumElements(); i++){ | |||
144 | decls->Nth(i)->Emit(); | |||
145 | } | |||
146 | for (int i = 0; i < stmts->NumElements(); i++){ | |||
147 | stmts->Nth(i)->Emit(); | |||
148 | } | |||
149 | ||||
150 | //TODO | |||
151 | ||||
152 | popScope(); | |||
153 | return NULL; | |||
154 | } | |||
155 | ||||
156 | llvm::Value * DeclStmt::Emit(){ | |||
157 | llvm::Value * val; | |||
158 | if (VarDecl * vd = dynamic_cast<VarDecl*>(this->decl)){ | |||
159 | val = vd->Emit(); | |||
160 | } | |||
161 | else if (FnDecl * fd = dynamic_cast<FnDecl*>(this->decl)){ | |||
162 | val = fd->Emit(); | |||
163 | } | |||
164 | else{ | |||
165 | val = NULL; | |||
166 | } | |||
167 | return val; | |||
168 | } | |||
169 | ||||
170 | llvm::Value * ConditionalStmt::Emit(){ | |||
171 | return NULL; | |||
172 | } | |||
173 | //for statement | |||
174 | //while statement | |||
175 | //if statement | |||
176 | ||||
177 | llvm::Value * BreakStmt::Emit(){ | |||
178 | return NULL; | |||
179 | } | |||
180 | ||||
181 | llvm::Value * ContinueStmt::Emit(){ | |||
182 | return NULL; | |||
183 | } | |||
184 | ||||
185 | //Not sure | |||
186 | llvm::Value * ReturnStmt::Emit(){ | |||
187 | llvm::Value * val; | |||
188 | llvm::LLVMContext * context = irGen->GetContext(); | |||
189 | if (expr){ | |||
190 | llvm::Value * retVal = expr->Emit(); | |||
191 | retVal = llvm::ReturnInst::Create(*context, retVal, irGen->GetBasicBlock()); | |||
192 | return retVal; | |||
193 | } | |||
194 | val = llvm::ReturnInst::Create(*context, irGen->GetBasicBlock()); |
ast_stmt.h
View file @
98c5b35
/* File: ast_stmt.h | 1 | 1 | /* File: ast_stmt.h | |
* ---------------- | 2 | 2 | * ---------------- | |
* The Stmt class and its subclasses are used to represent | 3 | 3 | * The Stmt class and its subclasses are used to represent | |
* statements in the parse tree. For each statment in the | 4 | 4 | * statements in the parse tree. For each statment in the | |
* language (for, if, return, etc.) there is a corresponding | 5 | 5 | * language (for, if, return, etc.) there is a corresponding | |
* node class for that construct. | 6 | 6 | * node class for that construct. | |
* | 7 | 7 | * | |
* pp3: You will need to extend the Stmt classes to generate | 8 | 8 | * pp3: You will need to extend the Stmt classes to generate | |
* LLVM IR instructions. | 9 | 9 | * LLVM IR instructions. | |
*/ | 10 | 10 | */ | |
11 | 11 | |||
12 | 12 | |||
#ifndef _H_ast_stmt | 13 | 13 | #ifndef _H_ast_stmt | |
#define _H_ast_stmt | 14 | 14 | #define _H_ast_stmt | |
15 | 15 | |||
#include "list.h" | 16 | 16 | #include "list.h" | |
#include "ast.h" | 17 | 17 | #include "ast.h" | |
18 | 18 | |||
class Decl; | 19 | 19 | class Decl; | |
class VarDecl; | 20 | 20 | class VarDecl; | |
class Expr; | 21 | 21 | class Expr; | |
class IntConstant; | 22 | 22 | class IntConstant; | |
23 | 23 | |||
void yyerror(const char *msg); | 24 | 24 | void yyerror(const char *msg); | |
25 | 25 | |||
class Program : public Node | 26 | 26 | class Program : public Node | |
{ | 27 | 27 | { | |
protected: | 28 | 28 | protected: | |
List<Decl*> *decls; | 29 | 29 | List<Decl*> *decls; | |
30 | 30 | |||
public: | 31 | 31 | public: | |
Program(List<Decl*> *declList); | 32 | 32 | Program(List<Decl*> *declList); | |
const char *GetPrintNameForNode() { return "Program"; } | 33 | 33 | const char *GetPrintNameForNode() { return "Program"; } | |
void PrintChildren(int indentLevel); | 34 | 34 | void PrintChildren(int indentLevel); | |
virtual llvm::Value* Emit(); | 35 | 35 | virtual llvm::Value* Emit(); | |
}; | 36 | 36 | }; | |
37 | 37 | |||
class Stmt : public Node | 38 | 38 | class Stmt : public Node | |
{ | 39 | 39 | { | |
public: | 40 | 40 | public: | |
Stmt() : Node() {} | 41 | 41 | Stmt() : Node() {} | |
Stmt(yyltype loc) : Node(loc) {} | 42 | 42 | Stmt(yyltype loc) : Node(loc) {} | |
}; | 43 | 43 | }; | |
44 | 44 | |||
class StmtBlock : public Stmt | 45 | 45 | class StmtBlock : public Stmt | |
{ | 46 | 46 | { | |
protected: | 47 | 47 | protected: | |
List<VarDecl*> *decls; | 48 | 48 | List<VarDecl*> *decls; | |
List<Stmt*> *stmts; | 49 | 49 | List<Stmt*> *stmts; | |
50 | 50 | |||
public: | 51 | 51 | public: | |
StmtBlock(List<VarDecl*> *variableDeclarations, List<Stmt*> *statements); | 52 | 52 | StmtBlock(List<VarDecl*> *variableDeclarations, List<Stmt*> *statements); | |
const char *GetPrintNameForNode() { return "StmtBlock"; } | 53 | 53 | const char *GetPrintNameForNode() { return "StmtBlock"; } | |
void PrintChildren(int indentLevel); | 54 | 54 | void PrintChildren(int indentLevel); | |
55 | ||||
56 | llvm::Value *Emit(); | |||
}; | 55 | 57 | }; | |
56 | 58 | |||
class DeclStmt: public Stmt | 57 | 59 | class DeclStmt: public Stmt | |
{ | 58 | 60 | { | |
protected: | 59 | 61 | protected: | |
Decl* decl; | 60 | 62 | Decl* decl; | |
61 | 63 | |||
public: | 62 | 64 | public: | |
DeclStmt(Decl *d); | 63 | 65 | DeclStmt(Decl *d); | |
const char *GetPrintNameForNode() { return "DeclStmt"; } | 64 | 66 | const char *GetPrintNameForNode() { return "DeclStmt"; } | |
void PrintChildren(int indentLevel); | 65 | 67 | void PrintChildren(int indentLevel); | |
66 | 68 | |||
69 | llvm::Value *Emit(); | |||
}; | 67 | 70 | }; | |
68 | 71 | |||
class ConditionalStmt : public Stmt | 69 | 72 | class ConditionalStmt : public Stmt | |
{ | 70 | 73 | { | |
protected: | 71 | 74 | protected: | |
Expr *test; | 72 | 75 | Expr *test; | |
Stmt *body; | 73 | 76 | Stmt *body; | |
74 | 77 | |||
public: | 75 | 78 | public: | |
ConditionalStmt() : Stmt(), test(NULL), body(NULL) {} | 76 | 79 | ConditionalStmt() : Stmt(), test(NULL), body(NULL) {} | |
ConditionalStmt(Expr *testExpr, Stmt *body); | 77 | 80 | ConditionalStmt(Expr *testExpr, Stmt *body); | |
78 | 81 | |||
82 | llvm::Value *Emit(); | |||
}; | 79 | 83 | }; | |
80 | 84 | |||
class LoopStmt : public ConditionalStmt | 81 | 85 | class LoopStmt : public ConditionalStmt | |
{ | 82 | 86 | { | |
public: | 83 | 87 | public: | |
LoopStmt(Expr *testExpr, Stmt *body) | 84 | 88 | LoopStmt(Expr *testExpr, Stmt *body) | |
: ConditionalStmt(testExpr, body) {} | 85 | 89 | : ConditionalStmt(testExpr, body) {} | |
}; | 86 | 90 | }; | |
87 | 91 | |||
class ForStmt : public LoopStmt | 88 | 92 | class ForStmt : public LoopStmt | |
{ | 89 | 93 | { | |
protected: | 90 | 94 | protected: | |
Expr *init, *step; | 91 | 95 | Expr *init, *step; | |
92 | 96 | |||
public: | 93 | 97 | public: | |
ForStmt(Expr *init, Expr *test, Expr *step, Stmt *body); | 94 | 98 | ForStmt(Expr *init, Expr *test, Expr *step, Stmt *body); | |
const char *GetPrintNameForNode() { return "ForStmt"; } | 95 | 99 | const char *GetPrintNameForNode() { return "ForStmt"; } | |
void PrintChildren(int indentLevel); | 96 | 100 | void PrintChildren(int indentLevel); | |
97 | 101 | |||
}; | 98 | 102 | }; | |
99 | 103 | |||
class WhileStmt : public LoopStmt | 100 | 104 | class WhileStmt : public LoopStmt | |
{ | 101 | 105 | { | |
public: | 102 | 106 | public: | |
WhileStmt(Expr *test, Stmt *body) : LoopStmt(test, body) {} | 103 | 107 | WhileStmt(Expr *test, Stmt *body) : LoopStmt(test, body) {} | |
const char *GetPrintNameForNode() { return "WhileStmt"; } | 104 | 108 | const char *GetPrintNameForNode() { return "WhileStmt"; } | |
void PrintChildren(int indentLevel); | 105 | 109 | void PrintChildren(int indentLevel); | |
106 | 110 | |||
}; | 107 | 111 | }; | |
108 | 112 | |||
class IfStmt : public ConditionalStmt | 109 | 113 | class IfStmt : public ConditionalStmt | |
{ | 110 | 114 | { | |
protected: | 111 | 115 | protected: | |
Stmt *elseBody; | 112 | 116 | Stmt *elseBody; | |
113 | 117 | |||
public: | 114 | 118 | public: | |
IfStmt() : ConditionalStmt(), elseBody(NULL) {} | 115 | 119 | IfStmt() : ConditionalStmt(), elseBody(NULL) {} | |
IfStmt(Expr *test, Stmt *thenBody, Stmt *elseBody); | 116 | 120 | IfStmt(Expr *test, Stmt *thenBody, Stmt *elseBody); | |
const char *GetPrintNameForNode() { return "IfStmt"; } | 117 | 121 | const char *GetPrintNameForNode() { return "IfStmt"; } | |
void PrintChildren(int indentLevel); | 118 | 122 | void PrintChildren(int indentLevel); | |
119 | 123 | |||
}; | 120 | 124 | }; | |
121 | 125 | |||
class IfStmtExprError : public IfStmt | 122 | 126 | class IfStmtExprError : public IfStmt | |
{ | 123 | 127 | { | |
public: | 124 | 128 | public: | |
IfStmtExprError() : IfStmt() { yyerror(this->GetPrintNameForNode()); } | 125 | 129 | IfStmtExprError() : IfStmt() { yyerror(this->GetPrintNameForNode()); } | |
const char *GetPrintNameForNode() { return "IfStmtExprError"; } | 126 | 130 | const char *GetPrintNameForNode() { return "IfStmtExprError"; } | |
}; | 127 | 131 | }; | |
128 | 132 | |||
class BreakStmt : public Stmt | 129 | 133 | class BreakStmt : public Stmt | |
{ | 130 | 134 | { | |
public: | 131 | 135 | public: | |
BreakStmt(yyltype loc) : Stmt(loc) {} | 132 | 136 | BreakStmt(yyltype loc) : Stmt(loc) {} | |
const char *GetPrintNameForNode() { return "BreakStmt"; } | 133 | 137 | const char *GetPrintNameForNode() { return "BreakStmt"; } | |
134 | 138 | |||
139 | llvm::Value *Emit(); | |||
}; | 135 | 140 | }; | |
136 | 141 | |||
class ContinueStmt : public Stmt | 137 | 142 | class ContinueStmt : public Stmt | |
{ | 138 | 143 | { | |
public: | 139 | 144 | public: | |
ContinueStmt(yyltype loc) : Stmt(loc) {} | 140 | 145 | ContinueStmt(yyltype loc) : Stmt(loc) {} | |
const char *GetPrintNameForNode() { return "ContinueStmt"; } | 141 | 146 | const char *GetPrintNameForNode() { return "ContinueStmt"; } | |
142 | 147 | |||
148 | llvm::Value *Emit(); | |||
}; | 143 | 149 | }; | |
144 | 150 | |||
class ReturnStmt : public Stmt | 145 | 151 | class ReturnStmt : public Stmt | |
{ | 146 | 152 | { | |
protected: | 147 | 153 | protected: | |
Expr *expr; | 148 | 154 | Expr *expr; | |
149 | 155 | |||
public: | 150 | 156 | public: | |
ReturnStmt(yyltype loc, Expr *expr = NULL); | 151 | 157 | ReturnStmt(yyltype loc, Expr *expr = NULL); | |
const char *GetPrintNameForNode() { return "ReturnStmt"; } | 152 | 158 | const char *GetPrintNameForNode() { return "ReturnStmt"; } | |
void PrintChildren(int indentLevel); | 153 | 159 | void PrintChildren(int indentLevel); | |
154 | 160 | |||
161 | llvm::Value *Emit(); | |||
}; | 155 | 162 | }; | |
156 | 163 | |||
class SwitchLabel : public Stmt | 157 | 164 | class SwitchLabel : public Stmt | |
{ | 158 | 165 | { | |
protected: | 159 | 166 | protected: | |
Expr *label; | 160 | 167 | Expr *label; | |
Stmt *stmt; | 161 | 168 | Stmt *stmt; | |
162 | 169 | |||
public: | 163 | 170 | public: | |
SwitchLabel() { label = NULL; stmt = NULL; } | 164 | 171 | SwitchLabel() { label = NULL; stmt = NULL; } | |
SwitchLabel(Expr *label, Stmt *stmt); | 165 | 172 | SwitchLabel(Expr *label, Stmt *stmt); | |
SwitchLabel(Stmt *stmt); | 166 | 173 | SwitchLabel(Stmt *stmt); | |
void PrintChildren(int indentLevel); | 167 | 174 | void PrintChildren(int indentLevel); | |
168 | 175 | |||
176 | llvm::Value *Emit(); | |||
}; | 169 | 177 | }; | |
170 | 178 |