Skip to content

Commit

Permalink
add return support
Browse files Browse the repository at this point in the history
  • Loading branch information
zhuzhenpeng committed Feb 25, 2016
1 parent 8ba809a commit 07c2fd4
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 4 deletions.
28 changes: 26 additions & 2 deletions src/ast_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,13 @@ ObjectPtr ArgumentsAST::eval(EnvPtr env, ObjectPtr caller) {
//每次调用函数,都有创建一个新的内部环境
EnvPtr funcEnv = func->runtimeEnv();
params->eval(funcEnv, env, children_);
auto result = func->block()->eval(funcEnv);
return result;
try {
func->block()->eval(funcEnv);
}
catch(ASTReturnException &e) {
return e.result_;
}
return nullptr;
}

ObjectPtr ArgumentsAST::invokeNative(EnvPtr env, NativeFuncPtr func) {
Expand Down Expand Up @@ -849,6 +854,25 @@ void NewAST::initInstance(ClassInfoPtr ci, EnvPtr env) {
}
}

/*******************return表达式*****************************/

ReturnAST::ReturnAST(): ASTList(ASTKind::LIST_RETURN, false) {}

ObjectPtr ReturnAST::eval(EnvPtr env) {
if (children_.empty())
throw ASTEvalException("invalid return statement");

ObjectPtr result = children_[0]->eval(env);
throw ASTReturnException(result);
}

std::string ReturnAST::info() {
if (children_.empty())
throw ASTEvalException("invalid return statement");

return "return " + children_[0]->info();
}

/*******************数组字面量*******************************/

ArrayLiteralAST::ArrayLiteralAST(): ASTList(ASTKind::LIST_ARRAY_LITERAL, false) {}
Expand Down
19 changes: 19 additions & 0 deletions src/ast_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,25 @@ class NewAST: public PostfixAST{
};
using NewASTPtr = std::shared_ptr<NewAST>;

/*******************return表达式*****************************/

class ReturnAST: public ASTList {
public:
ReturnAST();

//计算出结果后抛出异常给上层处理
ObjectPtr eval(EnvPtr env) override;

std::string info() override;
};
using ReturnASTPtr = std::shared_ptr<ReturnAST>;

class ASTReturnException: public ASTEvalException {
public:
ASTReturnException(ObjectPtr result): ASTEvalException("return"), result_(result) {}
ObjectPtr result_;
};

/*******************数组字面量*******************************/

class ArrayLiteralAST: public ASTList {
Expand Down
6 changes: 4 additions & 2 deletions src/ast_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class ASTEvalException: public ASTException {
ASTEvalException(const std::string &msg): ASTException(msg) {}
};


/******************************AST迭代器接口*****************************/
template <typename Item>
class Iterator {
Expand Down Expand Up @@ -73,8 +74,9 @@ enum class ASTKind {
LIST_CLASS_STMNT = 2018,
LIST_DOT = 2019,
LIST_NEW = 2020,
LIST_ARRAY_LITERAL = 2021,
LIST_ARRAY_REF = 2022
LIST_RETURN = 2021,
LIST_ARRAY_LITERAL = 2022,
LIST_ARRAY_REF = 2023
};

/*********************AST的基类,用于定义接口****************************/
Expand Down
3 changes: 3 additions & 0 deletions src/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ void BasicParser::init() {
Parser::rule(ASTKind::LIST_WHILE_STMNT)->custom("while", true)\
->commomPR(condition)->commomPR(block),

//return 语句
Parser::rule(ASTKind::LIST_RETURN)->custom("return", true)->commomPR(expr),

//普通的算术表达式
simple
});
Expand Down
3 changes: 3 additions & 0 deletions src/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* simple : expr
* statement : "if" condition block EOL {elif} ["else" block]
* | "while" condition block
* | "return" expr
* | simple
* elif : "elif" condition block EOL
* condition : expr
Expand All @@ -42,6 +43,8 @@
* 1. program允许以NULL作为分割符,主要是为了if块的“换行{”格式问题,if语句会把program中的
* EOL Token吞掉;
* 一般情况下,应该使用换行或者分号
*
* 2. simple其实可以被expr替代
*/

class BasicParser {
Expand Down
3 changes: 3 additions & 0 deletions src/parser_constructor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ ASTreePtr ASTFactory::getListInstance(ASTKind kind) {
case ASTKind::LIST_NEW:
result = std::make_shared<NewAST>();
break;
case ASTKind::LIST_RETURN:
result = std::make_shared<ReturnAST>();
break;
case ASTKind::LIST_ARRAY_REF:
result = std::make_shared<ArrayRefAST>();
break;
Expand Down
5 changes: 5 additions & 0 deletions testFiles/bar.spr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require foo as bar_foo

bar_foo.a = 101
print(bar_foo.fooInstance.age)

25 changes: 25 additions & 0 deletions testFiles/entry.spr
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Foo {
a_ = nil
b_ = nil

def init(a, b) {
self.a_ = a
self.b_ = b
}

def foo() {
print(a_ + b_)
}

def sumAB() {
num = a_ + b_
return num + 1
print("shit")
}
}

f = Foo.new(1, 2)
f.foo()

h = f.sumAB()
print(h)
4 changes: 4 additions & 0 deletions testFiles/foo.spr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require bar as barrr

a = 100

72 changes: 72 additions & 0 deletions testFiles/test.spr
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
print("test function")
def fact(n) {
f = 1
while n > 0 {
f = f * n
n = n - 1
}
return f
}
result = fact(3)
print("6 succes")

print("test fib")
def fib(n) {
if n < 2 {
return n
}
else {
return fib(n - 1) + fib(n - 2)
}
}
result = fib(10)
print("55 success")

print("test class")
class Position {
x = y = 0

def init() {

}

def move (nx, ny) {
x = nx
y = ny
}
}
p = Position.new()
p.move(3, 4)
p.x = 10
print(p.x + p.y)
print("14 success")

if 1 > 2 {
print ("1 > 2")
}
elif 3 < 2{
print ("3 < 2")
}
elif 3 < 2 {
print ("3 < 2")
}
else {
print ("else test successfully")
}

true = (1 < 2)
false = (1 > 2)

if or(true, false) {
print("or test successfully");
}
else {
print("or test failed")
}

if and(true, false) {
print("and test failed")
}
else {
print("and test successfully")
}

0 comments on commit 07c2fd4

Please sign in to comment.