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

View File

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

View File

@ -1,9 +1,32 @@
/*
* Unit tests
*/
test_call = fn () {
ret = fn(){[1,fn(){[4,5,6]},3]}()[1]()[1]
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 () {
assert(undefined == undefined)
assert(!(undefined != undefined))
@ -162,13 +185,14 @@ test_fib = fn () {
test_interpolated_string = fn () {
hello = "Hello"
world = "World!"
world = "World!"
ret = "{hello} {world}"
assert(ret == 'Hello World!')
}
debugger
test_call()
test_return()
test_closure()
test_undefined()
test_array()
@ -176,6 +200,9 @@ test_function()
test_object()
test_object_factory()
test_class()
debugger
test_sum()
test_fib()
test_interpolated_string()
return // end