diff --git a/captain.sh b/captain.sh index 9521df7..ff27030 100755 --- a/captain.sh +++ b/captain.sh @@ -1,7 +1,8 @@ #!/bin/bash kraken="kraken" -bootstrap_commits=(cf46fb13afe66ba475db9725e9269c9c1cd3bbc3 2cd43e5a217318c70097334b3598d2924f64b362 2051f54b559ac5edf67277d4f1134aca2cb9215d ecbbcb4eda56e2467efb0a04e7d668b95856aa4b d126cbf24ba8b26e3814e2260d555ecaee86508c) +bootstrap_commits=(cf46fb13afe66ba475db9725e9269c9c1cd3bbc3 2cd43e5a217318c70097334b3598d2924f64b362 2051f54b559ac5edf67277d4f1134aca2cb9215d ecbbcb4eda56e2467efb0a04e7d668b95856aa4b d126cbf24ba8b26e3814e2260d555ecaee86508c 947384cced5397a517a71963edc8f47e668d734f) + # Echo version string to a file included by kraken.krak # There is a default version string in the file in case kraken is not built with captain diff --git a/kraken.krak b/kraken.krak index e6d898c..46c04c9 100644 --- a/kraken.krak +++ b/kraken.krak @@ -8,7 +8,7 @@ import symbol:* import tree:* import serialize:* import c_generator:* -/*import interpreter:**/ +import interpreter:* import os:* import compiler_version @@ -78,8 +78,8 @@ fun main(argc: int, argv: **char):int { importer.import(kraken_file_name) if (interpret_instead) { println("Interpreting!") - /*var interpret.construct(importer.name_ast_map, importer.ast_pass.ast_to_syntax): interpreter*/ - /*interpret.call_main()*/ + var interpret.construct(importer.name_ast_map, importer.ast_pass.ast_to_syntax): interpreter + interpret.call_main() } else { println("Generating C") var c_generator.construct(): c_generator diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index 78b5a8a..5d1c5d8 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -1178,6 +1178,7 @@ fun get_ast_type(node: *ast_node): *type { ast_node::cast(backing) return backing.to_type ast_node::value(backing) return backing.value_type } + return null() } fun ast_to_dot(root: *ast_node): string { diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index bcd5b8a..b602810 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -926,7 +926,10 @@ obj ast_transformation (Object) { var second_param = null() if (func_name == "." || func_name == "->") { /*println("PRE VANILLA TRY FOR SECOND PARAM")*/ - second_param = transform(node->children[2], get_ast_type(first_param)->type_def, searching_for, template_replacements) + var first_param_type = get_ast_type(first_param) + if (!first_param_type) + error(node, "Cannot get type from left side of access operation") + second_param = transform(node->children[2], first_param_type->type_def, searching_for, template_replacements) // template member functions // XXX add in template inst if it exists if (!second_param) match (searching_for) { diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index 35c4491..035c13a 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -1,5 +1,6 @@ import io:* import map:* +import stack:* import string:* import util:* import tree:* @@ -9,12 +10,21 @@ import ast_transformation:* adt value { integer: int, - floating: float + floating: float, + double_floating: double, + void_nothing +} +adt control_flow { + nor, + con, + bre, + ret } fun print_value(v: ref value) { match (v) { value::integer(data) println(data) value::floating(data) println(data) + value::void_nothing() println("void") } } @@ -46,10 +56,127 @@ obj interpreter (Object) { if (results.size != 1) error(string("wrong number of mains to call: ") + results.size) println("calling main!") - print_value(interpret_function_call(results[0], vector())) + var var_stack = stack>() + print_value(call_function(results[0], vector(), &var_stack)) } - fun interpret_function_call(func: *ast_node, params: vector): value { - return value::integer(0) + fun interpret_function_call(func_call: *ast_node, var_stack: *stack>): pair { + // should handle dot style method call here + var parameters = func_call->function_call.parameters.map(fun(p: *ast_node): value return interpret(p, var_stack).first;) + return make_pair(call_function(func_call->function_call.func, parameters, var_stack), control_flow::nor()) + } + fun call_function(func: *ast_node, parameters: vector, var_stack: *stack>): value { + var_stack->push(map()) + // will need adjustment + var func_name = func->function.name + if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/" + || func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">=" + || func_name == "==" || func_name == "!=" || func_name == "%" || func_name == "^" + || func_name == "|" || func_name == "&" + )) + return do_basic_op(func_name, parameters[0], parameters[1]) + if (parameters.size != func->function.parameters.size) + error(string("calling function ") + func->function.name + " with wrong number of parameters") + for (var i = 0; i < parameters.size; i++;) + var_stack->top()[func->function.parameters[i]->identifier.name] = parameters[i] + var to_ret = interpret(func->function.body_statement, var_stack).first + var_stack->pop() + return to_ret + } + fun interpret_statement(stmt: *ast_node, var_stack: *stack>): pair { + return interpret(stmt->statement.child, var_stack) + } + fun interpret_code_block(block: *ast_node, var_stack: *stack>): pair { + var_stack->push(map()) + for (var i = 0; i < block->code_block.children.size; i++;) { + var statement = interpret(block->code_block.children[i], var_stack) + match (statement.second) { + control_flow::con() { + var_stack->pop() + return make_pair(value::void_nothing(), control_flow::con()) + } + control_flow::bre() { + var_stack->pop() + return make_pair(value::void_nothing(), control_flow::bre()) + } + control_flow::ret() { + var_stack->pop() + return statement + } + } + // if nor, continue on + } + var_stack->pop() + return make_pair(value::void_nothing(), control_flow::nor()) + } + fun interpret_return_statement(stmt: *ast_node, var_stack: *stack>): pair { + return make_pair(interpret(stmt->return_statement.return_value, var_stack).first, control_flow::ret()) + } + fun interpret_value(val: *ast_node): pair + return make_pair(wrap_value(val), control_flow::nor()) + fun interpret(node: *ast_node, var_stack: *stack>): pair { + match (*node) { + ast_node::function_call(backing) return interpret_function_call(node, var_stack) + ast_node::statement(backing) return interpret_statement(node, var_stack) + ast_node::code_block(backing) return interpret_code_block(node, var_stack) + ast_node::return_statement(backing) return interpret_return_statement(node, var_stack) + ast_node::value(backing) return interpret_value(node) + } + error(string("Cannot interpret node: ") + get_ast_name(node)) + } + fun do_basic_op(func_name: string, a: value, b: value): value { + match (a) { + value::integer(av) { + match (b) { + value::integer(bv) return value::integer(do_op(func_name, av, bv)) + } + } + } + return value::integer(a.integer + b.integer) + } + fun do_op(op: string, a: T, b: U): W { + if (op == "+") return a + b + if (op == "-") return a - b + if (op == "*") return a * b + if (op == "/") return a / b + if (op == "<") return a < b + if (op == ">") return a > b + if (op == "<=") return a <= b + if (op == ">=") return a >= b + if (op == "==") return a == b + if (op == "!=") return a != b + if (op == "%") return a % b + if (op == "^") return a ^ b + if (op == "|") return a | b + if (op == "&") return a & b + + error(("Invalid op: ") + op) + } + fun wrap_value(val: *ast_node): value { + var value_str = val->value.string_value + if (value_str[0] == '"') // " // Comment hack for emacs now + return value::integer(1) + else if (value_str[0] == '\'') //'// lol, comment hack for vim syntax highlighting (my fault, of course) + return value::integer(1) + else if (value_str == "true" || value_str == "false") + return value::integer(1) + else { + // should differentiate between float and double... + var contains_dot = false + for (var i = 0; i < value_str.length(); i++;) { + if (value_str[i] == '.') { + contains_dot = true + break + } + } + if (contains_dot) + if (value_str[value_str.length()-1] == 'f') + return value::floating(1.0f) + else + return value::double_floating(1.0) + else + return value::integer(string_to_int(value_str)) + } + return value::void_nothing() } } diff --git a/stdlib/string.krak b/stdlib/string.krak index 0259a79..74a0e5e 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -19,6 +19,24 @@ fun to_string(in: long): string fun to_string(in: ulong): string return to_string_num(in) +fun string_to_int(it: string): int { + var is_negative = false + if (it[0] == '-') { + is_negative = true + it = it.slice(1,-1) + } + var result = 0 + var power = 1 + while (it.length()) { + result += power * (it.last() - '0') + it = it.slice(0,-2) + power *= 10 + } + if (is_negative) + return -result + return result +} + fun to_string_num(in: T): string { if (in == 0) return string("0") @@ -197,6 +215,7 @@ obj string (Object, Serializable) { out.add(current) return out } + fun last(): char return data.last() fun lines(): vector::vector return split('\n') fun split(delim: char): vector::vector { var out.construct(): vector::vector