Added 'return' statement.

This commit is contained in:
yhirose 2015-08-04 18:03:05 -04:00
parent 3cb801a5df
commit ff6deb98e3
3 changed files with 65 additions and 11 deletions

View File

@ -6,10 +6,12 @@ syn match culError ";"
syn match culError "\s*$" syn match culError "\s*$"
syn match culLineComment "\(\/\/\|#\).*" contains=@Spell,javaScriptCommentTodo syn match culLineComment "\(\/\/\|#\).*" contains=@Spell,javaScriptCommentTodo
syn keyword culKeyword fn syn keyword culFunction fn
syn keyword culSelf self syn keyword culSelf self
syn keyword culConditional if else syn keyword culConditional if else
syn keyword culRepeat while syn keyword culRepeat while
syn keyword culReturn return
syn keyword culDebugger debugger
syn keyword culBoolean true false syn keyword culBoolean true false
syn keyword culCommentTodo TODO FIXME XXX TBD contained syn keyword culCommentTodo TODO FIXME XXX TBD contained
syn keyword culStorage mut syn keyword culStorage mut
@ -24,10 +26,12 @@ hi def link culCommentTodo Todo
hi def link culConditional Conditional hi def link culConditional Conditional
hi def link culDecNumber Number hi def link culDecNumber Number
hi def link culFuncCall Function hi def link culFuncCall Function
hi def link culKeyword Keyword hi def link culFunction Type
hi def link culLineComment Comment hi def link culLineComment Comment
hi def link culOperator Operator hi def link culOperator Operator
hi def link culRepeat Repeat hi def link culRepeat Repeat
hi def link culReturn Statement
hi def link culDebugger Debug
hi def link culSelf Constant hi def link culSelf Constant
hi def link culStorage StorageClass hi def link culStorage StorageClass
hi def link culStringD String hi def link culStringD String

View File

@ -9,9 +9,10 @@ const auto grammar_ = R"(
PROGRAM <- _ STATEMENTS PROGRAM <- _ STATEMENTS
STATEMENTS <- (STATEMENT (';' _)?)* STATEMENTS <- (STATEMENT (';' _)?)*
STATEMENT <- DEBUGGER / EXPRESSION STATEMENT <- DEBUGGER / RETURN / EXPRESSION
DEBUGGER <- 'debugger' _ DEBUGGER <- 'debugger' _
RETURN <- 'return' __ '\n' / 'return' _ EXPRESSION?
EXPRESSION <- ASSIGNMENT / LOGICAL_OR EXPRESSION <- ASSIGNMENT / LOGICAL_OR
@ -67,10 +68,11 @@ const auto grammar_ = R"(
MUTABLE <- < 'mut'? > _ MUTABLE <- < 'mut'? > _
~_ <- (Space / EndOfLine / Comment)* ~_ <- (Space / EndOfLine / Comment)*
~__ <- (Space / Comment)*
Space <- ' ' / '\t' Space <- ' ' / '\t'
EndOfLine <- '\r\n' / '\n' / '\r' EndOfLine <- '\r\n' / '\n' / '\r'
EndOfFile <- !. EndOfFile <- !.
Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* (EndOfLine / EndOfFile) Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* &(EndOfLine / EndOfFile)
)"; )";
@ -526,12 +528,21 @@ inline void setup_built_in_functions(Environment& env) {
false); false);
} }
struct Eval struct Interpreter
{ {
Eval(Debugger debugger = nullptr) Interpreter(Debugger debugger = nullptr)
: debugger_(debugger) { : debugger_(debugger) {
} }
Value exec(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
try {
return eval(ast, env);
} catch (const Value& val) {
return val;
}
}
private:
Value eval(const peglib::Ast& ast, std::shared_ptr<Environment> env) { Value eval(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
using peglib::operator"" _; using peglib::operator"" _;
@ -566,6 +577,7 @@ struct Eval
case "NUMBER"_: return eval_number(ast, env); case "NUMBER"_: return eval_number(ast, env);
case "INTERPOLATED_STRING"_: return eval_interpolated_string(ast, env); case "INTERPOLATED_STRING"_: return eval_interpolated_string(ast, env);
case "DEBUGGER"_: return Value(); case "DEBUGGER"_: return Value();
case "RETURN"_: eval_return(ast, env);
} }
if (ast.is_token) { if (ast.is_token) {
@ -576,7 +588,6 @@ struct Eval
throw std::logic_error("invalid Ast type"); throw std::logic_error("invalid Ast type");
} }
private:
Value eval_statements(const peglib::Ast& ast, std::shared_ptr<Environment> env) { Value eval_statements(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
if (ast.is_token) { if (ast.is_token) {
return eval(ast, env); return eval(ast, env);
@ -654,7 +665,11 @@ private:
} }
callEnv->initialize("__LINE__", Value((long)ast.line), false); callEnv->initialize("__LINE__", Value((long)ast.line), false);
callEnv->initialize("__COLUMN__", Value((long)ast.column), false); callEnv->initialize("__COLUMN__", Value((long)ast.column), false);
return f.eval(callEnv); try {
return f.eval(callEnv);
} catch (const Value& val) {
return val;
}
} }
std::string msg = "arguments error..."; std::string msg = "arguments error...";
@ -901,6 +916,14 @@ private:
return Value(std::move(s)); return Value(std::move(s));
}; };
void eval_return(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
if (ast.nodes.empty()) {
throw Value();
} else {
throw eval(*ast.nodes[0], env);
}
}
Debugger debugger_; Debugger debugger_;
}; };
@ -924,8 +947,8 @@ inline bool run(
}; };
if (parser.parse_n(expr, len, ast, path.c_str())) { if (parser.parse_n(expr, len, ast, path.c_str())) {
ast = peglib::AstOptimizer(true, { "PARAMETERS", "ARGUMENTS", "OBJECT", "ARRAY" }).optimize(ast); ast = peglib::AstOptimizer(true, { "PARAMETERS", "ARGUMENTS", "OBJECT", "ARRAY", "RETURN" }).optimize(ast);
val = Eval(debugger).eval(*ast, env); val = Interpreter(debugger).exec(*ast, env);
return true; return true;
} }
} catch (std::runtime_error& e) { } catch (std::runtime_error& e) {

View File

@ -1,9 +1,32 @@
/*
* Unit tests
*/
test_call = fn () { test_call = fn () {
ret = fn(){[1,fn(){[4,5,6]},3]}()[1]()[1] ret = fn(){[1,fn(){[4,5,6]},3]}()[1]()[1]
assert(ret == 5) assert(ret == 5)
} }
test_return = fn () {
f = fn (x) {
if (x % 2) {
return 'odd'
}
'even'
}
assert(f(3) == 'odd')
assert(f(4) == 'even')
mut val = 0
f2 = fn () {
val = 1
return // comment
val = 2
}
f2()
assert(val == 1)
}
test_undefined = fn () { test_undefined = fn () {
assert(undefined == undefined) assert(undefined == undefined)
assert(!(undefined != undefined)) assert(!(undefined != undefined))
@ -162,13 +185,14 @@ test_fib = fn () {
test_interpolated_string = fn () { test_interpolated_string = fn () {
hello = "Hello" hello = "Hello"
world = "World!" world = "World!"
ret = "{hello} {world}" ret = "{hello} {world}"
assert(ret == 'Hello World!') assert(ret == 'Hello World!')
} }
debugger debugger
test_call() test_call()
test_return()
test_closure() test_closure()
test_undefined() test_undefined()
test_array() test_array()
@ -176,6 +200,9 @@ test_function()
test_object() test_object()
test_object_factory() test_object_factory()
test_class() test_class()
debugger
test_sum() test_sum()
test_fib() test_fib()
test_interpolated_string() test_interpolated_string()
return // end