Commit e3f7f8a769534ba879c06192a44f65b245112578
Exists in
master
Merge branch 'master' of git.ucsd.edu:acs008/cse131-pa4
Showing 5 changed files Inline Diff
ast_expr.cc
View file @
e3f7f8a
/* File: ast_expr.cc | 1 | 1 | /* File: ast_expr.cc | |
* ----------------- | 2 | 2 | * ----------------- | |
* Implementation of expression node classes. | 3 | 3 | * Implementation of expression node classes. | |
*/ | 4 | 4 | */ | |
5 | 5 | |||
#include <string.h> | 6 | 6 | #include <string.h> | |
#include "ast_expr.h" | 7 | 7 | #include "ast_expr.h" | |
#include "ast_type.h" | 8 | 8 | #include "ast_type.h" | |
#include "ast_decl.h" | 9 | 9 | #include "ast_decl.h" | |
#include "symtable.h" | 10 | 10 | #include "symtable.h" | |
11 | 11 | |||
IntConstant::IntConstant(yyltype loc, int val) : Expr(loc) { | 12 | 12 | IntConstant::IntConstant(yyltype loc, int val) : Expr(loc) { | |
value = val; | 13 | 13 | value = val; | |
} | 14 | 14 | } | |
void IntConstant::PrintChildren(int indentLevel) { | 15 | 15 | void IntConstant::PrintChildren(int indentLevel) { | |
printf("%d", value); | 16 | 16 | printf("%d", value); | |
} | 17 | 17 | } | |
18 | 18 | |||
FloatConstant::FloatConstant(yyltype loc, double val) : Expr(loc) { | 19 | 19 | FloatConstant::FloatConstant(yyltype loc, double val) : Expr(loc) { | |
value = val; | 20 | 20 | value = val; | |
} | 21 | 21 | } | |
void FloatConstant::PrintChildren(int indentLevel) { | 22 | 22 | void FloatConstant::PrintChildren(int indentLevel) { | |
printf("%g", value); | 23 | 23 | printf("%g", value); | |
} | 24 | 24 | } | |
25 | 25 | |||
BoolConstant::BoolConstant(yyltype loc, bool val) : Expr(loc) { | 26 | 26 | BoolConstant::BoolConstant(yyltype loc, bool val) : Expr(loc) { | |
value = val; | 27 | 27 | value = val; | |
} | 28 | 28 | } | |
void BoolConstant::PrintChildren(int indentLevel) { | 29 | 29 | void BoolConstant::PrintChildren(int indentLevel) { | |
printf("%s", value ? "true" : "false"); | 30 | 30 | printf("%s", value ? "true" : "false"); | |
} | 31 | 31 | } | |
32 | 32 | |||
VarExpr::VarExpr(yyltype loc, Identifier *ident) : Expr(loc) { | 33 | 33 | VarExpr::VarExpr(yyltype loc, Identifier *ident) : Expr(loc) { | |
Assert(ident != NULL); | 34 | 34 | Assert(ident != NULL); | |
this->id = ident; | 35 | 35 | this->id = ident; | |
} | 36 | 36 | } | |
37 | 37 | |||
void VarExpr::PrintChildren(int indentLevel) { | 38 | 38 | void VarExpr::PrintChildren(int indentLevel) { | |
id->Print(indentLevel+1); | 39 | 39 | id->Print(indentLevel+1); | |
} | 40 | 40 | } | |
41 | 41 | |||
Operator::Operator(yyltype loc, const char *tok) : Node(loc) { | 42 | 42 | Operator::Operator(yyltype loc, const char *tok) : Node(loc) { | |
Assert(tok != NULL); | 43 | 43 | Assert(tok != NULL); | |
strncpy(tokenString, tok, sizeof(tokenString)); | 44 | 44 | strncpy(tokenString, tok, sizeof(tokenString)); | |
} | 45 | 45 | } | |
46 | 46 | |||
void Operator::PrintChildren(int indentLevel) { | 47 | 47 | void Operator::PrintChildren(int indentLevel) { | |
printf("%s",tokenString); | 48 | 48 | printf("%s",tokenString); | |
} | 49 | 49 | } | |
50 | 50 | |||
bool Operator::IsOp(const char *op) const { | 51 | 51 | bool Operator::IsOp(const char *op) const { | |
return strcmp(tokenString, op) == 0; | 52 | 52 | return strcmp(tokenString, op) == 0; | |
} | 53 | 53 | } | |
54 | 54 | |||
CompoundExpr::CompoundExpr(Expr *l, Operator *o, Expr *r) | 55 | 55 | CompoundExpr::CompoundExpr(Expr *l, Operator *o, Expr *r) | |
: Expr(Join(l->GetLocation(), r->GetLocation())) { | 56 | 56 | : Expr(Join(l->GetLocation(), r->GetLocation())) { | |
Assert(l != NULL && o != NULL && r != NULL); | 57 | 57 | Assert(l != NULL && o != NULL && r != NULL); | |
(op=o)->SetParent(this); | 58 | 58 | (op=o)->SetParent(this); | |
(left=l)->SetParent(this); | 59 | 59 | (left=l)->SetParent(this); | |
(right=r)->SetParent(this); | 60 | 60 | (right=r)->SetParent(this); | |
} | 61 | 61 | } | |
62 | 62 | |||
CompoundExpr::CompoundExpr(Operator *o, Expr *r) | 63 | 63 | CompoundExpr::CompoundExpr(Operator *o, Expr *r) | |
: Expr(Join(o->GetLocation(), r->GetLocation())) { | 64 | 64 | : Expr(Join(o->GetLocation(), r->GetLocation())) { | |
Assert(o != NULL && r != NULL); | 65 | 65 | Assert(o != NULL && r != NULL); | |
left = NULL; | 66 | 66 | left = NULL; | |
(op=o)->SetParent(this); | 67 | 67 | (op=o)->SetParent(this); | |
(right=r)->SetParent(this); | 68 | 68 | (right=r)->SetParent(this); | |
} | 69 | 69 | } | |
70 | 70 | |||
CompoundExpr::CompoundExpr(Expr *l, Operator *o) | 71 | 71 | CompoundExpr::CompoundExpr(Expr *l, Operator *o) | |
: Expr(Join(l->GetLocation(), o->GetLocation())) { | 72 | 72 | : Expr(Join(l->GetLocation(), o->GetLocation())) { | |
Assert(l != NULL && o != NULL); | 73 | 73 | Assert(l != NULL && o != NULL); | |
(left=l)->SetParent(this); | 74 | 74 | (left=l)->SetParent(this); | |
(op=o)->SetParent(this); | 75 | 75 | (op=o)->SetParent(this); | |
} | 76 | 76 | } | |
77 | 77 | |||
void CompoundExpr::PrintChildren(int indentLevel) { | 78 | 78 | void CompoundExpr::PrintChildren(int indentLevel) { | |
if (left) left->Print(indentLevel+1); | 79 | 79 | if (left) left->Print(indentLevel+1); | |
op->Print(indentLevel+1); | 80 | 80 | op->Print(indentLevel+1); | |
if (right) right->Print(indentLevel+1); | 81 | 81 | if (right) right->Print(indentLevel+1); | |
} | 82 | 82 | } | |
83 | 83 | |||
ConditionalExpr::ConditionalExpr(Expr *c, Expr *t, Expr *f) | 84 | 84 | ConditionalExpr::ConditionalExpr(Expr *c, Expr *t, Expr *f) | |
: Expr(Join(c->GetLocation(), f->GetLocation())) { | 85 | 85 | : Expr(Join(c->GetLocation(), f->GetLocation())) { | |
Assert(c != NULL && t != NULL && f != NULL); | 86 | 86 | Assert(c != NULL && t != NULL && f != NULL); | |
(cond=c)->SetParent(this); | 87 | 87 | (cond=c)->SetParent(this); | |
(trueExpr=t)->SetParent(this); | 88 | 88 | (trueExpr=t)->SetParent(this); | |
(falseExpr=f)->SetParent(this); | 89 | 89 | (falseExpr=f)->SetParent(this); | |
} | 90 | 90 | } | |
91 | 91 | |||
void ConditionalExpr::PrintChildren(int indentLevel) { | 92 | 92 | void ConditionalExpr::PrintChildren(int indentLevel) { | |
cond->Print(indentLevel+1, "(cond) "); | 93 | 93 | cond->Print(indentLevel+1, "(cond) "); | |
trueExpr->Print(indentLevel+1, "(true) "); | 94 | 94 | trueExpr->Print(indentLevel+1, "(true) "); | |
falseExpr->Print(indentLevel+1, "(false) "); | 95 | 95 | falseExpr->Print(indentLevel+1, "(false) "); | |
} | 96 | 96 | } | |
ArrayAccess::ArrayAccess(yyltype loc, Expr *b, Expr *s) : LValue(loc) { | 97 | 97 | ArrayAccess::ArrayAccess(yyltype loc, Expr *b, Expr *s) : LValue(loc) { | |
(base=b)->SetParent(this); | 98 | 98 | (base=b)->SetParent(this); | |
(subscript=s)->SetParent(this); | 99 | 99 | (subscript=s)->SetParent(this); | |
} | 100 | 100 | } | |
101 | 101 | |||
void ArrayAccess::PrintChildren(int indentLevel) { | 102 | 102 | void ArrayAccess::PrintChildren(int indentLevel) { | |
base->Print(indentLevel+1); | 103 | 103 | base->Print(indentLevel+1); | |
subscript->Print(indentLevel+1, "(subscript) "); | 104 | 104 | subscript->Print(indentLevel+1, "(subscript) "); | |
} | 105 | 105 | } | |
106 | 106 | |||
FieldAccess::FieldAccess(Expr *b, Identifier *f) | 107 | 107 | FieldAccess::FieldAccess(Expr *b, Identifier *f) | |
: LValue(b? Join(b->GetLocation(), f->GetLocation()) : *f->GetLocation()) { | 108 | 108 | : LValue(b? Join(b->GetLocation(), f->GetLocation()) : *f->GetLocation()) { | |
Assert(f != NULL); // b can be be NULL (just means no explicit base) | 109 | 109 | Assert(f != NULL); // b can be be NULL (just means no explicit base) | |
base = b; | 110 | 110 | base = b; | |
if (base) base->SetParent(this); | 111 | 111 | if (base) base->SetParent(this); | |
(field=f)->SetParent(this); | 112 | 112 | (field=f)->SetParent(this); | |
} | 113 | 113 | } | |
114 | 114 | |||
115 | 115 | |||
void FieldAccess::PrintChildren(int indentLevel) { | 116 | 116 | void FieldAccess::PrintChildren(int indentLevel) { | |
if (base) base->Print(indentLevel+1); | 117 | 117 | if (base) base->Print(indentLevel+1); | |
field->Print(indentLevel+1); | 118 | 118 | field->Print(indentLevel+1); | |
} | 119 | 119 | } | |
120 | 120 | |||
Call::Call(yyltype loc, Expr *b, Identifier *f, List<Expr*> *a) : Expr(loc) { | 121 | 121 | Call::Call(yyltype loc, Expr *b, Identifier *f, List<Expr*> *a) : Expr(loc) { | |
Assert(f != NULL && a != NULL); // b can be be NULL (just means no explicit base) | 122 | 122 | Assert(f != NULL && a != NULL); // b can be be NULL (just means no explicit base) | |
base = b; | 123 | 123 | base = b; | |
if (base) base->SetParent(this); | 124 | 124 | if (base) base->SetParent(this); |
ast_expr.h
View file @
e3f7f8a
/* File: ast_expr.h | 1 | 1 | /* File: ast_expr.h | |
* ---------------- | 2 | 2 | * ---------------- | |
* The Expr class and its subclasses are used to represent | 3 | 3 | * The Expr class and its subclasses are used to represent | |
* expressions in the parse tree. For each expression in the | 4 | 4 | * expressions in the parse tree. For each expression in the | |
* language (add, call, New, etc.) there is a corresponding | 5 | 5 | * language (add, call, New, 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 Expr classes to implement | 8 | 8 | * pp3: You will need to extend the Expr classes to implement | |
* semantic analysis for rules pertaining to expressions. | 9 | 9 | * semantic analysis for rules pertaining to expressions. | |
*/ | 10 | 10 | */ | |
11 | 11 | |||
12 | 12 | |||
#ifndef _H_ast_expr | 13 | 13 | #ifndef _H_ast_expr | |
#define _H_ast_expr | 14 | 14 | #define _H_ast_expr | |
15 | 15 | |||
#include "ast.h" | 16 | 16 | #include "ast.h" | |
#include "ast_stmt.h" | 17 | 17 | #include "ast_stmt.h" | |
#include "list.h" | 18 | 18 | #include "list.h" | |
#include "ast_type.h" | 19 | 19 | #include "ast_type.h" | |
20 | 20 | |||
void yyerror(const char *msg); | 21 | 21 | void yyerror(const char *msg); | |
22 | 22 | |||
class Expr : public Stmt | 23 | 23 | class Expr : public Stmt | |
{ | 24 | 24 | { | |
public: | 25 | 25 | public: | |
Expr(yyltype loc) : Stmt(loc) {} | 26 | 26 | Expr(yyltype loc) : Stmt(loc) {} | |
Expr() : Stmt() {} | 27 | 27 | Expr() : Stmt() {} | |
28 | 28 | |||
friend std::ostream& operator<< (std::ostream& stream, Expr * expr) { | 29 | 29 | friend std::ostream& operator<< (std::ostream& stream, Expr * expr) { | |
return stream << expr->GetPrintNameForNode(); | 30 | 30 | return stream << expr->GetPrintNameForNode(); | |
} | 31 | 31 | } | |
}; | 32 | 32 | }; | |
33 | 33 | |||
class ExprError : public Expr | 34 | 34 | class ExprError : public Expr | |
{ | 35 | 35 | { | |
public: | 36 | 36 | public: | |
ExprError() : Expr() { yyerror(this->GetPrintNameForNode()); } | 37 | 37 | ExprError() : Expr() { yyerror(this->GetPrintNameForNode()); } | |
const char *GetPrintNameForNode() { return "ExprError"; } | 38 | 38 | const char *GetPrintNameForNode() { return "ExprError"; } | |
}; | 39 | 39 | }; | |
40 | 40 | |||
/* This node type is used for those places where an expression is optional. | 41 | 41 | /* This node type is used for those places where an expression is optional. | |
* We could use a NULL pointer, but then it adds a lot of checking for | 42 | 42 | * We could use a NULL pointer, but then it adds a lot of checking for | |
* NULL. By using a valid, but no-op, node, we save that trouble */ | 43 | 43 | * NULL. By using a valid, but no-op, node, we save that trouble */ | |
class EmptyExpr : public Expr | 44 | 44 | class EmptyExpr : public Expr | |
{ | 45 | 45 | { | |
public: | 46 | 46 | public: | |
const char *GetPrintNameForNode() { return "Empty"; } | 47 | 47 | const char *GetPrintNameForNode() { return "Empty"; } | |
}; | 48 | 48 | }; | |
49 | 49 | |||
class IntConstant : public Expr | 50 | 50 | class IntConstant : public Expr | |
{ | 51 | 51 | { | |
protected: | 52 | 52 | protected: | |
int value; | 53 | 53 | int value; | |
54 | 54 | |||
public: | 55 | 55 | public: | |
IntConstant(yyltype loc, int val); | 56 | 56 | IntConstant(yyltype loc, int val); | |
const char *GetPrintNameForNode() { return "IntConstant"; } | 57 | 57 | const char *GetPrintNameForNode() { return "IntConstant"; } | |
void PrintChildren(int indentLevel); | 58 | 58 | void PrintChildren(int indentLevel); | |
59 | llvm::Value* Emit(); | |||
}; | 59 | 60 | }; | |
60 | 61 | |||
class FloatConstant: public Expr | 61 | 62 | class FloatConstant: public Expr | |
{ | 62 | 63 | { | |
protected: | 63 | 64 | protected: | |
double value; | 64 | 65 | double value; | |
65 | 66 | |||
public: | 66 | 67 | public: | |
FloatConstant(yyltype loc, double val); | 67 | 68 | FloatConstant(yyltype loc, double val); | |
const char *GetPrintNameForNode() { return "FloatConstant"; } | 68 | 69 | const char *GetPrintNameForNode() { return "FloatConstant"; } | |
void PrintChildren(int indentLevel); | 69 | 70 | void PrintChildren(int indentLevel); | |
71 | llvm::Value* Emit(); | |||
}; | 70 | 72 | }; | |
71 | 73 | |||
class BoolConstant : public Expr | 72 | 74 | class BoolConstant : public Expr | |
{ | 73 | 75 | { | |
protected: | 74 | 76 | protected: | |
bool value; | 75 | 77 | bool value; | |
76 | 78 | |||
public: | 77 | 79 | public: | |
BoolConstant(yyltype loc, bool val); | 78 | 80 | BoolConstant(yyltype loc, bool val); | |
const char *GetPrintNameForNode() { return "BoolConstant"; } | 79 | 81 | const char *GetPrintNameForNode() { return "BoolConstant"; } | |
void PrintChildren(int indentLevel); | 80 | 82 | void PrintChildren(int indentLevel); | |
83 | llvm::Value* Emit(); | |||
}; | 81 | 84 | }; | |
82 | 85 | |||
class VarExpr : public Expr | 83 | 86 | class VarExpr : public Expr | |
{ | 84 | 87 | { | |
protected: | 85 | 88 | protected: | |
Identifier *id; | 86 | 89 | Identifier *id; | |
87 | 90 | |||
public: | 88 | 91 | public: | |
VarExpr(yyltype loc, Identifier *id); | 89 | 92 | VarExpr(yyltype loc, Identifier *id); | |
const char *GetPrintNameForNode() { return "VarExpr"; } | 90 | 93 | const char *GetPrintNameForNode() { return "VarExpr"; } | |
void PrintChildren(int indentLevel); | 91 | 94 | void PrintChildren(int indentLevel); | |
Identifier *GetIdentifier() {return id;} | 92 | 95 | Identifier *GetIdentifier() {return id;} | |
}; | 93 | 96 | }; | |
94 | 97 | |||
class Operator : public Node | 95 | 98 | class Operator : public Node | |
{ | 96 | 99 | { | |
protected: | 97 | 100 | protected: | |
char tokenString[4]; | 98 | 101 | char tokenString[4]; | |
99 | 102 | |||
public: | 100 | 103 | public: | |
Operator(yyltype loc, const char *tok); | 101 | 104 | Operator(yyltype loc, const char *tok); | |
const char *GetPrintNameForNode() { return "Operator"; } | 102 | 105 | const char *GetPrintNameForNode() { return "Operator"; } | |
void PrintChildren(int indentLevel); | 103 | 106 | void PrintChildren(int indentLevel); | |
friend ostream& operator<<(ostream& out, Operator *o) { return out << o->tokenString; } | 104 | 107 | friend ostream& operator<<(ostream& out, Operator *o) { return out << o->tokenString; } | |
bool IsOp(const char *op) const; | 105 | 108 | bool IsOp(const char *op) const; | |
}; | 106 | 109 | }; | |
107 | 110 | |||
class CompoundExpr : public Expr | 108 | 111 | class CompoundExpr : public Expr | |
{ | 109 | 112 | { | |
protected: | 110 | 113 | protected: | |
Operator *op; | 111 | 114 | Operator *op; | |
Expr *left, *right; // left will be NULL if unary | 112 | 115 | Expr *left, *right; // left will be NULL if unary | |
113 | 116 | |||
public: | 114 | 117 | public: | |
CompoundExpr(Expr *lhs, Operator *op, Expr *rhs); // for binary | 115 | 118 | CompoundExpr(Expr *lhs, Operator *op, Expr *rhs); // for binary | |
CompoundExpr(Operator *op, Expr *rhs); // for unary | 116 | 119 | CompoundExpr(Operator *op, Expr *rhs); // for unary | |
CompoundExpr(Expr *lhs, Operator *op); // for unary | 117 | 120 | CompoundExpr(Expr *lhs, Operator *op); // for unary | |
void PrintChildren(int indentLevel); | 118 | 121 | void PrintChildren(int indentLevel); | |
}; | 119 | 122 | }; | |
120 | 123 | |||
class ArithmeticExpr : public CompoundExpr | 121 | 124 | class ArithmeticExpr : public CompoundExpr | |
{ | 122 | 125 | { | |
public: | 123 | 126 | public: | |
ArithmeticExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | 124 | 127 | ArithmeticExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | |
ArithmeticExpr(Operator *op, Expr *rhs) : CompoundExpr(op,rhs) {} | 125 | 128 | ArithmeticExpr(Operator *op, Expr *rhs) : CompoundExpr(op,rhs) {} | |
const char *GetPrintNameForNode() { return "ArithmeticExpr"; } | 126 | 129 | const char *GetPrintNameForNode() { return "ArithmeticExpr"; } | |
}; | 127 | 130 | }; | |
128 | 131 | |||
class RelationalExpr : public CompoundExpr | 129 | 132 | class RelationalExpr : public CompoundExpr | |
{ | 130 | 133 | { | |
public: | 131 | 134 | public: | |
RelationalExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | 132 | 135 | RelationalExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | |
const char *GetPrintNameForNode() { return "RelationalExpr"; } | 133 | 136 | const char *GetPrintNameForNode() { return "RelationalExpr"; } | |
}; | 134 | 137 | }; | |
135 | 138 | |||
class EqualityExpr : public CompoundExpr | 136 | 139 | class EqualityExpr : public CompoundExpr | |
{ | 137 | 140 | { | |
public: | 138 | 141 | public: | |
EqualityExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | 139 | 142 | EqualityExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | |
const char *GetPrintNameForNode() { return "EqualityExpr"; } | 140 | 143 | const char *GetPrintNameForNode() { return "EqualityExpr"; } | |
}; | 141 | 144 | }; | |
142 | 145 | |||
class LogicalExpr : public CompoundExpr | 143 | 146 | class LogicalExpr : public CompoundExpr | |
{ | 144 | 147 | { | |
public: | 145 | 148 | public: | |
LogicalExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | 146 | 149 | LogicalExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | |
LogicalExpr(Operator *op, Expr *rhs) : CompoundExpr(op,rhs) {} | 147 | 150 | LogicalExpr(Operator *op, Expr *rhs) : CompoundExpr(op,rhs) {} | |
const char *GetPrintNameForNode() { return "LogicalExpr"; } | 148 | 151 | const char *GetPrintNameForNode() { return "LogicalExpr"; } | |
}; | 149 | 152 | }; | |
150 | 153 | |||
class AssignExpr : public CompoundExpr | 151 | 154 | class AssignExpr : public CompoundExpr | |
{ | 152 | 155 | { | |
public: | 153 | 156 | public: | |
AssignExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | 154 | 157 | AssignExpr(Expr *lhs, Operator *op, Expr *rhs) : CompoundExpr(lhs,op,rhs) {} | |
const char *GetPrintNameForNode() { return "AssignExpr"; } | 155 | 158 | const char *GetPrintNameForNode() { return "AssignExpr"; } | |
}; | 156 | 159 | }; | |
157 | 160 | |||
class PostfixExpr : public CompoundExpr | 158 | 161 | class PostfixExpr : public CompoundExpr | |
{ | 159 | 162 | { | |
public: | 160 | 163 | public: | |
PostfixExpr(Expr *lhs, Operator *op) : CompoundExpr(lhs,op) {} | 161 | 164 | PostfixExpr(Expr *lhs, Operator *op) : CompoundExpr(lhs,op) {} | |
const char *GetPrintNameForNode() { return "PostfixExpr"; } | 162 | 165 | const char *GetPrintNameForNode() { return "PostfixExpr"; } | |
163 | 166 | |||
}; | 164 | 167 | }; | |
165 | 168 | |||
class ConditionalExpr : public Expr | 166 | 169 | class ConditionalExpr : public Expr | |
{ | 167 | 170 | { | |
protected: | 168 | 171 | protected: | |
Expr *cond, *trueExpr, *falseExpr; | 169 | 172 | Expr *cond, *trueExpr, *falseExpr; | |
public: | 170 | 173 | public: | |
ConditionalExpr(Expr *c, Expr *t, Expr *f); | 171 | 174 | ConditionalExpr(Expr *c, Expr *t, Expr *f); | |
void PrintChildren(int indentLevel); | 172 | 175 | void PrintChildren(int indentLevel); | |
const char *GetPrintNameForNode() { return "ConditionalExpr"; } | 173 | 176 | const char *GetPrintNameForNode() { return "ConditionalExpr"; } | |
}; | 174 | 177 | }; | |
175 | 178 | |||
class LValue : public Expr | 176 | 179 | class LValue : public Expr | |
{ | 177 | 180 | { | |
public: | 178 | 181 | public: | |
LValue(yyltype loc) : Expr(loc) {} | 179 | 182 | LValue(yyltype loc) : Expr(loc) {} | |
}; | 180 | 183 | }; | |
181 | 184 | |||
class ArrayAccess : public LValue | 182 | 185 | class ArrayAccess : public LValue | |
{ | 183 | 186 | { | |
protected: | 184 | 187 | protected: | |
Expr *base, *subscript; | 185 | 188 | Expr *base, *subscript; | |
186 | 189 | |||
public: | 187 | 190 | public: | |
ArrayAccess(yyltype loc, Expr *base, Expr *subscript); | 188 | 191 | ArrayAccess(yyltype loc, Expr *base, Expr *subscript); | |
const char *GetPrintNameForNode() { return "ArrayAccess"; } | 189 | 192 | const char *GetPrintNameForNode() { return "ArrayAccess"; } | |
void PrintChildren(int indentLevel); | 190 | 193 | void PrintChildren(int indentLevel); | |
}; | 191 | 194 | }; | |
192 | 195 | |||
/* Note that field access is used both for qualified names | 193 | 196 | /* Note that field access is used both for qualified names | |
* base.field and just field without qualification. We don't | 194 | 197 | * base.field and just field without qualification. We don't | |
* know for sure whether there is an implicit "this." in | 195 | 198 | * know for sure whether there is an implicit "this." in | |
* front until later on, so we use one node type for either | 196 | 199 | * front until later on, so we use one node type for either | |
* and sort it out later. */ | 197 | 200 | * and sort it out later. */ | |
class FieldAccess : public LValue | 198 | 201 | class FieldAccess : public LValue |
ast_stmt.cc
View file @
e3f7f8a
/* 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 | |||
llvm::Value* Program::Emit() { | 26 | 26 | llvm::Value* Program::Emit() { | |
// TODO: | 27 | 27 | // TODO: | |
// This is just a reference for you to get started | 28 | 28 | // This is just a reference for you to get started | |
// | 29 | 29 | // | |
// You can use this as a template and create Emit() function | 30 | 30 | // You can use this as a template and create Emit() function | |
// for individual node to fill in the module structure and instructions. | 31 | 31 | // for individual node to fill in the module structure and instructions. | |
// | 32 | 32 | // | |
IRGenerator irgen; | 33 | 33 | //IRGenerator irgen; | |
llvm::Module *mod = irgen.GetOrCreateModule("Name_the_Module.bc"); | 34 | 34 | llvm::Module *mod = irgen.GetOrCreateModule("Name_the_Module.bc"); | |
35 | 35 | |||
// create a function signature | 36 | 36 | // create a function signature | |
std::vector<llvm::Type *> argTypes; | 37 | 37 | std::vector<llvm::Type *> argTypes; | |
llvm::Type *intTy = irgen.GetIntType(); | 38 | 38 | llvm::Type *intTy = irgen.GetIntType(); | |
argTypes.push_back(intTy); | 39 | 39 | argTypes.push_back(intTy); | |
llvm::ArrayRef<llvm::Type *> argArray(argTypes); | 40 | 40 | llvm::ArrayRef<llvm::Type *> argArray(argTypes); | |
llvm::FunctionType *funcTy = llvm::FunctionType::get(intTy, argArray, false); | 41 | 41 | llvm::FunctionType *funcTy = llvm::FunctionType::get(intTy, argArray, false); | |
42 | 42 | |||
// llvm::Function *f = llvm::cast<llvm::Function>(mod->getOrInsertFunction("foo", intTy, intTy, (Type *)0)); | 43 | 43 | // llvm::Function *f = llvm::cast<llvm::Function>(mod->getOrInsertFunction("foo", intTy, intTy, (Type *)0)); | |
llvm::Function *f = llvm::cast<llvm::Function>(mod->getOrInsertFunction("Name_the_function", funcTy)); | 44 | 44 | llvm::Function *f = llvm::cast<llvm::Function>(mod->getOrInsertFunction("Name_the_function", funcTy)); | |
llvm::Argument *arg = f->arg_begin(); | 45 | 45 | llvm::Argument *arg = f->arg_begin(); | |
arg->setName("x"); | 46 | 46 | arg->setName("x"); | |
47 | 47 | |||
// insert a block into the runction | 48 | 48 | // insert a block into the runction | |
llvm::LLVMContext *context = irgen.GetContext(); | 49 | 49 | llvm::LLVMContext *context = irgen.GetContext(); | |
llvm::BasicBlock *bb = llvm::BasicBlock::Create(*context, "entry", f); | 50 | 50 | llvm::BasicBlock *bb = llvm::BasicBlock::Create(*context, "entry", f); | |
51 | 51 | |||
// create a return instruction | 52 | 52 | // create a return instruction | |
llvm::Value *val = llvm::ConstantInt::get(intTy, 1); | 53 | 53 | llvm::Value *val = llvm::ConstantInt::get(intTy, 1); | |
llvm::Value *sum = llvm::BinaryOperator::CreateAdd(arg, val, "", bb); | 54 | 54 | llvm::Value *sum = llvm::BinaryOperator::CreateAdd(arg, val, "", bb); | |
llvm::ReturnInst::Create(*context, sum, bb); | 55 | 55 | llvm::ReturnInst::Create(*context, sum, bb); | |
56 | 56 | |||
// write the BC into standard output | 57 | 57 | // write the BC into standard output | |
llvm::WriteBitcodeToFile(mod, llvm::outs()); | 58 | 58 | llvm::WriteBitcodeToFile(mod, llvm::outs()); | |
} | 59 | 59 | } | |
60 | 60 | |||
StmtBlock::StmtBlock(List<VarDecl*> *d, List<Stmt*> *s) { | 61 | 61 | StmtBlock::StmtBlock(List<VarDecl*> *d, List<Stmt*> *s) { | |
Assert(d != NULL && s != NULL); | 62 | 62 | Assert(d != NULL && s != NULL); | |
(decls=d)->SetParentAll(this); | 63 | 63 | (decls=d)->SetParentAll(this); | |
(stmts=s)->SetParentAll(this); | 64 | 64 | (stmts=s)->SetParentAll(this); | |
} | 65 | 65 | } | |
66 | 66 | |||
void StmtBlock::PrintChildren(int indentLevel) { | 67 | 67 | void StmtBlock::PrintChildren(int indentLevel) { | |
decls->PrintAll(indentLevel+1); | 68 | 68 | decls->PrintAll(indentLevel+1); | |
stmts->PrintAll(indentLevel+1); | 69 | 69 | stmts->PrintAll(indentLevel+1); | |
} | 70 | 70 | } | |
71 | 71 | |||
DeclStmt::DeclStmt(Decl *d) { | 72 | 72 | DeclStmt::DeclStmt(Decl *d) { | |
Assert(d != NULL); | 73 | 73 | Assert(d != NULL); | |
(decl=d)->SetParent(this); | 74 | 74 | (decl=d)->SetParent(this); | |
} | 75 | 75 | } | |
76 | 76 | |||
void DeclStmt::PrintChildren(int indentLevel) { | 77 | 77 | void DeclStmt::PrintChildren(int indentLevel) { | |
decl->Print(indentLevel+1); | 78 | 78 | decl->Print(indentLevel+1); | |
} | 79 | 79 | } | |
80 | 80 | |||
ConditionalStmt::ConditionalStmt(Expr *t, Stmt *b) { | 81 | 81 | ConditionalStmt::ConditionalStmt(Expr *t, Stmt *b) { | |
Assert(t != NULL && b != NULL); | 82 | 82 | Assert(t != NULL && b != NULL); | |
(test=t)->SetParent(this); | 83 | 83 | (test=t)->SetParent(this); | |
(body=b)->SetParent(this); | 84 | 84 | (body=b)->SetParent(this); | |
} | 85 | 85 | } | |
86 | 86 | |||
ForStmt::ForStmt(Expr *i, Expr *t, Expr *s, Stmt *b): LoopStmt(t, b) { | 87 | 87 | ForStmt::ForStmt(Expr *i, Expr *t, Expr *s, Stmt *b): LoopStmt(t, b) { | |
Assert(i != NULL && t != NULL && b != NULL); | 88 | 88 | Assert(i != NULL && t != NULL && b != NULL); | |
(init=i)->SetParent(this); | 89 | 89 | (init=i)->SetParent(this); | |
step = s; | 90 | 90 | step = s; | |
if ( s ) | 91 | 91 | if ( s ) | |
(step=s)->SetParent(this); | 92 | 92 | (step=s)->SetParent(this); | |
} | 93 | 93 | } | |
94 | 94 | |||
void ForStmt::PrintChildren(int indentLevel) { | 95 | 95 | void ForStmt::PrintChildren(int indentLevel) { | |
init->Print(indentLevel+1, "(init) "); | 96 | 96 | init->Print(indentLevel+1, "(init) "); | |
test->Print(indentLevel+1, "(test) "); | 97 | 97 | test->Print(indentLevel+1, "(test) "); | |
if ( step ) | 98 | 98 | if ( step ) | |
step->Print(indentLevel+1, "(step) "); | 99 | 99 | step->Print(indentLevel+1, "(step) "); | |
body->Print(indentLevel+1, "(body) "); | 100 | 100 | body->Print(indentLevel+1, "(body) "); | |
} | 101 | 101 | } | |
102 | 102 | |||
void WhileStmt::PrintChildren(int indentLevel) { | 103 | 103 | void WhileStmt::PrintChildren(int indentLevel) { | |
test->Print(indentLevel+1, "(test) "); | 104 | 104 | test->Print(indentLevel+1, "(test) "); | |
body->Print(indentLevel+1, "(body) "); | 105 | 105 | body->Print(indentLevel+1, "(body) "); | |
} | 106 | 106 | } | |
107 | 107 | |||
IfStmt::IfStmt(Expr *t, Stmt *tb, Stmt *eb): ConditionalStmt(t, tb) { | 108 | 108 | IfStmt::IfStmt(Expr *t, Stmt *tb, Stmt *eb): ConditionalStmt(t, tb) { | |
Assert(t != NULL && tb != NULL); // else can be NULL | 109 | 109 | Assert(t != NULL && tb != NULL); // else can be NULL | |
elseBody = eb; | 110 | 110 | elseBody = eb; | |
if (elseBody) elseBody->SetParent(this); | 111 | 111 | if (elseBody) elseBody->SetParent(this); | |
} | 112 | 112 | } | |
113 | 113 | |||
void IfStmt::PrintChildren(int indentLevel) { | 114 | 114 | void IfStmt::PrintChildren(int indentLevel) { | |
if (test) test->Print(indentLevel+1, "(test) "); | 115 | 115 | if (test) test->Print(indentLevel+1, "(test) "); | |
if (body) body->Print(indentLevel+1, "(then) "); | 116 | 116 | if (body) body->Print(indentLevel+1, "(then) "); | |
if (elseBody) elseBody->Print(indentLevel+1, "(else) "); | 117 | 117 | if (elseBody) elseBody->Print(indentLevel+1, "(else) "); | |
} | 118 | 118 | } | |
119 | 119 | |||
120 | 120 | |||
ReturnStmt::ReturnStmt(yyltype loc, Expr *e) : Stmt(loc) { | 121 | 121 | ReturnStmt::ReturnStmt(yyltype loc, Expr *e) : Stmt(loc) { | |
expr = e; | 122 | 122 | expr = e; | |
if (e != NULL) expr->SetParent(this); | 123 | 123 | if (e != NULL) expr->SetParent(this); | |
} | 124 | 124 | } | |
125 | 125 | |||
void ReturnStmt::PrintChildren(int indentLevel) { | 126 | 126 | void ReturnStmt::PrintChildren(int indentLevel) { | |
if ( expr ) | 127 | 127 | if ( expr ) | |
expr->Print(indentLevel+1); | 128 | 128 | expr->Print(indentLevel+1); | |
} | 129 | 129 | } | |
130 | 130 | |||
SwitchLabel::SwitchLabel(Expr *l, Stmt *s) { | 131 | 131 | SwitchLabel::SwitchLabel(Expr *l, Stmt *s) { | |
Assert(l != NULL && s != NULL); | 132 | 132 | Assert(l != NULL && s != NULL); | |
(label=l)->SetParent(this); | 133 | 133 | (label=l)->SetParent(this); |
irgen.cc
View file @
e3f7f8a
/* irgen.cc - LLVM IR generator | 1 | 1 | /* irgen.cc - LLVM IR generator | |
* | 2 | 2 | * | |
* You can implement any LLVM related functions here. | 3 | 3 | * You can implement any LLVM related functions here. | |
*/ | 4 | 4 | */ | |
5 | 5 | |||
#include "irgen.h" | 6 | 6 | #include "irgen.h" | |
7 | 7 | |||
8 | IRGenerator irgen; | |||
9 | ||||
IRGenerator::IRGenerator() : | 8 | 10 | IRGenerator::IRGenerator() : | |
context(NULL), | 9 | 11 | context(NULL), | |
module(NULL), | 10 | 12 | module(NULL), | |
currentFunc(NULL), | 11 | 13 | currentFunc(NULL), | |
currentBB(NULL) | 12 | 14 | currentBB(NULL) | |
{ | 13 | 15 | { | |
} | 14 | 16 | } | |
15 | 17 | |||
IRGenerator::~IRGenerator() { | 16 | 18 | IRGenerator::~IRGenerator() { | |
} | 17 | 19 | } | |
18 | 20 | |||
llvm::Module *IRGenerator::GetOrCreateModule(const char *moduleID) | 19 | 21 | llvm::Module *IRGenerator::GetOrCreateModule(const char *moduleID) | |
{ | 20 | 22 | { | |
if ( module == NULL ) { | 21 | 23 | if ( module == NULL ) { | |
context = new llvm::LLVMContext(); | 22 | 24 | context = new llvm::LLVMContext(); | |
module = new llvm::Module(moduleID, *context); | 23 | 25 | module = new llvm::Module(moduleID, *context); | |
module->setTargetTriple(TargetTriple); | 24 | 26 | module->setTargetTriple(TargetTriple); | |
module->setDataLayout(TargetLayout); | 25 | 27 | module->setDataLayout(TargetLayout); | |
} | 26 | 28 | } | |
return module; | 27 | 29 | return module; | |
} | 28 | 30 | } | |
29 | 31 | |||
void IRGenerator::SetFunction(llvm::Function *func) { | 30 | 32 | void IRGenerator::SetFunction(llvm::Function *func) { | |
currentFunc = func; | 31 | 33 | currentFunc = func; | |
} | 32 | 34 | } | |
33 | 35 | |||
llvm::Function *IRGenerator::GetFunction() const { | 34 | 36 | llvm::Function *IRGenerator::GetFunction() const { | |
return currentFunc; | 35 | 37 | return currentFunc; | |
} | 36 | 38 | } | |
37 | 39 | |||
void IRGenerator::SetBasicBlock(llvm::BasicBlock *bb) { | 38 | 40 | void IRGenerator::SetBasicBlock(llvm::BasicBlock *bb) { | |
currentBB = bb; | 39 | 41 | currentBB = bb; | |
} | 40 | 42 | } | |
41 | 43 | |||
llvm::BasicBlock *IRGenerator::GetBasicBlock() const { | 42 | 44 | llvm::BasicBlock *IRGenerator::GetBasicBlock() const { | |
return currentBB; | 43 | 45 | return currentBB; | |
} | 44 | 46 | } | |
45 | 47 | |||
llvm::Type *IRGenerator::GetIntType() const { | 46 | 48 | llvm::Type *IRGenerator::GetIntType() const { | |
llvm::Type *ty = llvm::Type::getInt32Ty(*context); | 47 | 49 | llvm::Type *ty = llvm::Type::getInt32Ty(*context); | |
return ty; | 48 | 50 | return ty; | |
} | 49 | 51 | } | |
50 | 52 |
irgen.h
View file @
e3f7f8a
/** | 1 | 1 | /** | |
* File: irgen.h | 2 | 2 | * File: irgen.h | |
* ----------- | 3 | 3 | * ----------- | |
* This file defines a class for LLVM IR Generation. | 4 | 4 | * This file defines a class for LLVM IR Generation. | |
* | 5 | 5 | * | |
* All LLVM instruction related functions or utilities can be implemented | 6 | 6 | * All LLVM instruction related functions or utilities can be implemented | |
* here. You'll need to customize this class heavily to provide any helpers | 7 | 7 | * here. You'll need to customize this class heavily to provide any helpers | |
* or untility as you need. | 8 | 8 | * or untility as you need. | |
*/ | 9 | 9 | */ | |
10 | 10 | |||
#ifndef _H_IRGen | 11 | 11 | #ifndef _H_IRGen | |
#define _H_IRGen | 12 | 12 | #define _H_IRGen | |
13 | 13 | |||
// LLVM headers | 14 | 14 | // LLVM headers | |
#include "llvm/IR/Module.h" | 15 | 15 | #include "llvm/IR/Module.h" | |
#include "llvm/IR/LLVMContext.h" | 16 | 16 | #include "llvm/IR/LLVMContext.h" | |
#include "llvm/IR/Instructions.h" | 17 | 17 | #include "llvm/IR/Instructions.h" | |
#include "llvm/IR/Constants.h" | 18 | 18 | #include "llvm/IR/Constants.h" | |
19 | 19 | |||
class IRGenerator { | 20 | 20 | class IRGenerator { | |
public: | 21 | 21 | public: | |
IRGenerator(); | 22 | 22 | IRGenerator(); | |
~IRGenerator(); | 23 | 23 | ~IRGenerator(); | |
24 | 24 | |||
llvm::Module *GetOrCreateModule(const char *moduleID); | 25 | 25 | llvm::Module *GetOrCreateModule(const char *moduleID); | |
llvm::LLVMContext *GetContext() const { return context; } | 26 | 26 | llvm::LLVMContext *GetContext() const { return context; } | |
27 | 27 | |||
// Add your helper functions here | 28 | 28 | // Add your helper functions here | |
llvm::Function *GetFunction() const; | 29 | 29 | llvm::Function *GetFunction() const; | |
void SetFunction(llvm::Function *func); | 30 | 30 | void SetFunction(llvm::Function *func); | |
31 | 31 | |||
llvm::BasicBlock *GetBasicBlock() const; | 32 | 32 | llvm::BasicBlock *GetBasicBlock() const; | |
void SetBasicBlock(llvm::BasicBlock *bb); | 33 | 33 | void SetBasicBlock(llvm::BasicBlock *bb); | |
34 | 34 | |||
llvm::Type *GetIntType() const; | 35 | 35 | llvm::Type *GetIntType() const; | |
llvm::Type *GetBoolType() const; | 36 | 36 | llvm::Type *GetBoolType() const; | |
llvm::Type *GetFloatType() const; | 37 | 37 | llvm::Type *GetFloatType() const; | |
38 | 38 | |||
private: | 39 | 39 | private: | |
llvm::LLVMContext *context; | 40 | 40 | llvm::LLVMContext *context; | |
llvm::Module *module; | 41 | 41 | llvm::Module *module; | |
42 | 42 |