Enough interpreter to do math on constant integers

This commit is contained in:
Nathan Braswell
2016-05-13 03:10:36 -04:00
parent 3fe72bc8e2
commit e63b7cf770
6 changed files with 160 additions and 9 deletions

View File

@@ -1,7 +1,8 @@
#!/bin/bash #!/bin/bash
kraken="kraken" 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 # 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 # There is a default version string in the file in case kraken is not built with captain

View File

@@ -8,7 +8,7 @@ import symbol:*
import tree:* import tree:*
import serialize:* import serialize:*
import c_generator:* import c_generator:*
/*import interpreter:**/ import interpreter:*
import os:* import os:*
import compiler_version import compiler_version
@@ -78,8 +78,8 @@ fun main(argc: int, argv: **char):int {
importer.import(kraken_file_name) importer.import(kraken_file_name)
if (interpret_instead) { if (interpret_instead) {
println("Interpreting!") println("Interpreting!")
/*var interpret.construct(importer.name_ast_map, importer.ast_pass.ast_to_syntax): interpreter*/ var interpret.construct(importer.name_ast_map, importer.ast_pass.ast_to_syntax): interpreter
/*interpret.call_main()*/ interpret.call_main()
} else { } else {
println("Generating C") println("Generating C")
var c_generator.construct(): c_generator var c_generator.construct(): c_generator

View File

@@ -1178,6 +1178,7 @@ fun get_ast_type(node: *ast_node): *type {
ast_node::cast(backing) return backing.to_type ast_node::cast(backing) return backing.to_type
ast_node::value(backing) return backing.value_type ast_node::value(backing) return backing.value_type
} }
return null<type>()
} }
fun ast_to_dot(root: *ast_node): string { fun ast_to_dot(root: *ast_node): string {

View File

@@ -926,7 +926,10 @@ obj ast_transformation (Object) {
var second_param = null<ast_node>() var second_param = null<ast_node>()
if (func_name == "." || func_name == "->") { if (func_name == "." || func_name == "->") {
/*println("PRE VANILLA TRY FOR SECOND PARAM")*/ /*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 // template member functions
// XXX add in template inst if it exists // XXX add in template inst if it exists
if (!second_param) match (searching_for) { if (!second_param) match (searching_for) {

View File

@@ -1,5 +1,6 @@
import io:* import io:*
import map:* import map:*
import stack:*
import string:* import string:*
import util:* import util:*
import tree:* import tree:*
@@ -9,12 +10,21 @@ import ast_transformation:*
adt value { adt value {
integer: int, integer: int,
floating: float floating: float,
double_floating: double,
void_nothing
}
adt control_flow {
nor,
con,
bre,
ret
} }
fun print_value(v: ref value) { fun print_value(v: ref value) {
match (v) { match (v) {
value::integer(data) println(data) value::integer(data) println(data)
value::floating(data) println(data) value::floating(data) println(data)
value::void_nothing() println("void")
} }
} }
@@ -46,10 +56,127 @@ obj interpreter (Object) {
if (results.size != 1) if (results.size != 1)
error(string("wrong number of mains to call: ") + results.size) error(string("wrong number of mains to call: ") + results.size)
println("calling main!") println("calling main!")
print_value(interpret_function_call(results[0], vector<value>())) var var_stack = stack<map<string, value>>()
print_value(call_function(results[0], vector<value>(), &var_stack))
} }
fun interpret_function_call(func: *ast_node, params: vector<value>): value { fun interpret_function_call(func_call: *ast_node, var_stack: *stack<map<string, value>>): pair<value, control_flow> {
return value::integer(0) // 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<value>, var_stack: *stack<map<string, value>>): value {
var_stack->push(map<string,value>())
// 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<map<string, value>>): pair<value, control_flow> {
return interpret(stmt->statement.child, var_stack)
}
fun interpret_code_block(block: *ast_node, var_stack: *stack<map<string, value>>): pair<value, control_flow> {
var_stack->push(map<string,value>())
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<map<string, value>>): pair<value, control_flow> {
return make_pair(interpret(stmt->return_statement.return_value, var_stack).first, control_flow::ret())
}
fun interpret_value(val: *ast_node): pair<value, control_flow>
return make_pair(wrap_value(val), control_flow::nor())
fun interpret(node: *ast_node, var_stack: *stack<map<string, value>>): pair<value, control_flow> {
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<int,int,int>(func_name, av, bv))
}
}
}
return value::integer(a.integer + b.integer)
}
fun do_op<T,U,W>(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()
} }
} }

View File

@@ -19,6 +19,24 @@ fun to_string(in: long): string
fun to_string(in: ulong): string fun to_string(in: ulong): string
return to_string_num(in) 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<T>(in: T): string { fun to_string_num<T>(in: T): string {
if (in == 0) if (in == 0)
return string("0") return string("0")
@@ -197,6 +215,7 @@ obj string (Object, Serializable) {
out.add(current) out.add(current)
return out return out
} }
fun last(): char return data.last()
fun lines(): vector::vector<string> return split('\n') fun lines(): vector::vector<string> return split('\n')
fun split(delim: char): vector::vector<string> { fun split(delim: char): vector::vector<string> {
var out.construct(): vector::vector<string> var out.construct(): vector::vector<string>