Interpreter up to 71/73 tests passing, the only ones that don't yet are the future ones. Struct size is still wrong though

This commit is contained in:
Nathan Braswell
2016-07-03 01:55:32 -07:00
parent 2e80682f01
commit 87c2b1d2c1
7 changed files with 63 additions and 17 deletions

View File

@@ -7,6 +7,8 @@ import util:*
import tree:*
import symbol:*
import ast_nodes:*
// for error with syntax tree
import ast_transformation:*
import poset:*
fun code_triple(): code_triple return code_triple(string(), string(), string());
@@ -464,6 +466,9 @@ obj c_generator (Object) {
var function_return_type = get_ast_type(enclosing_func)->return_type
var to_ret = code_triple()
if (!function_return_type->is_void() && !function_return_type->equality(get_ast_type(return_value), false))
error(ast_to_syntax[node], "return value type does not match function return type")
to_ret += "return"
var refamp = string()
if (function_return_type->is_ref)

View File

@@ -80,6 +80,9 @@ fun wrap_value(val: *ast_node): value {
} else if (value_str[i] == '\\' && value_str[i+1] == 't') {
to_ret += '\t'
i++
} else if (value_str[i] == '\\' && value_str[i+1] == '\\') {
to_ret += '\\'
i++
} else if (i == value_str.length()-2) {
to_ret += value_str[i]
to_ret += value_str[i+1]
@@ -189,6 +192,15 @@ fun do_basic_op(func_name: string, a: value, b: value): value {
value::floating(av) return do_basic_floating_op_second_half(func_name, av, b, null<type>())
value::double_precision(av) return do_basic_floating_op_second_half(func_name, av, b, null<type>())
value::pointer(av) {
var real_b = get_real_value(b)
if (func_name == "==") {
if (!is_pointer(real_b)) {
print("equality between pointer and not pointer: ")
print_value(real_b)
error(":/")
}
return value::boolean(av.first == real_b.pointer.first)
}
var inc_in_bytes = cast_value(b, type_ptr(base_type::ulong_int())).ulong_int * type_size(av.second->clone_with_decreased_indirection())
var ptr = null<void>()
if (func_name == "+") {
@@ -196,7 +208,9 @@ fun do_basic_op(func_name: string, a: value, b: value): value {
} else if (func_name == "-") {
ptr = ((av.first) cast *char - inc_in_bytes) cast *void
} else {
error("pointer arithmatic is not + or -")
println(string("pointer arithmatic is not + or -: ") + func_name + ", b is: ")
print_value(b)
error(string("pointer arithmatic is not + or -: ") + func_name)
}
return value::pointer(make_pair(ptr, av.second))
}
@@ -486,9 +500,9 @@ fun type_size(t: *type): ulong {
error(string("Invalid type for type_size: ") + t->to_string())
}
fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong {
if (struct_type->type_def->type_def.is_union)
return 0
var size: ulong = 0
if (struct_type->type_def->type_def.is_union)
return size
for (var i = 0; i < struct_type->type_def->type_def.variables.size; i++;)
if (struct_type->type_def->type_def.variables[i]->declaration_statement.identifier == ident)
break
@@ -496,6 +510,8 @@ fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong {
size += type_size(struct_type->type_def->type_def.variables[i]->declaration_statement.identifier->identifier.type)
return size
}
fun dereference_pointer_into_variable(dereference_val: value): value
return value::variable(make_pair(get_real_value(dereference_val).pointer.first, dereference_val.pointer.second->clone_with_decreased_indirection()))
fun pop_and_free(var_stack: *stack<map<*ast_node, value>>) {
var_stack->pop().for_each(fun(k: *ast_node, v: value) {
match(v) {
@@ -595,6 +611,12 @@ obj interpreter (Object) {
var func_value = get_real_value(interpret(func_call_func, var_stack, enclosing_object, enclosing_func).first)
func_call_func = func_value.function.first
possible_closure_map = *func_value.function.second
// if the closure closes over this, put it as the enclosing object inside the closure
possible_closure_map.for_each(fun(key: *ast_node, v: value) {
if (key->identifier.name == "this") {
new_enclosing_object = get_real_value(dereference_pointer_into_variable(v))
}
})
/*println("possible_closure_map is")*/
/*possible_closure_map.for_each(fun(key: *ast_node, v: value) print(get_ast_name(key) + " ");)*/
/*println()*/
@@ -674,7 +696,7 @@ obj interpreter (Object) {
dereference_val = do_basic_op(string("+"), parameters[0], parameters[1])
if (!is_pointer(get_real_value(parameters[0])))
error("Trying to take dereference not a pointer")
return make_pair(value::variable(make_pair(get_real_value(dereference_val).pointer.first, dereference_val.pointer.second->clone_with_decreased_indirection())), control_flow::nor())
return make_pair(dereference_pointer_into_variable(dereference_val), control_flow::nor())
}
// check for built-in-ish externs (everything the standard library needs)
if (func_name == "printf" || func_name == "malloc" || func_name == "free" || func_name == "memmove" || func_name == "fflush" || func_name == "snprintf" || func_name == "fopen" || func_name == "fclose" || func_name == "ftell" || func_name == "fseek" || func_name == "fread" || func_name == "fwrite" || func_name == "atan" || func_name == "atan2" || func_name == "acos" || func_name == "asin" || func_name == "tan" || func_name == "cos" || func_name == "sin")
@@ -981,12 +1003,22 @@ obj interpreter (Object) {
// check for global
if (globals.contains_key(ident))
return make_pair(globals[ident], control_flow::nor())
println("couldn't find it in interpret identifier")
println("couldn't find it in interpret identifier, scope:")
for (var i = 0; i < var_stack->size(); i++;) {
println(string("level: ") + i)
var_stack->from_top(i).for_each(fun(key: *ast_node, v: value) print(get_ast_name(key) + " ");)
println()
}
if (is_object_like(enclosing_object)) {
println("object scope:")
var object_def = enclosing_object.object_like.second->type_def
for (var i = 0; i < object_def->type_def.variables.size; i++;) {
print(get_ast_name(object_def->type_def.variables[i]) + " ")
}
} else {
print("no object scope: ")
print_value(enclosing_object)
}
error(string("Cannot find variable: ") + ident->identifier.name)
}
fun interpret_cast(node: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> {

View File

@@ -170,7 +170,12 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
return;
if (!ident_type->is_ref && ident_type->indirection == 0 && ident_type->is_object()) {
if (backing.expression && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(backing.expression)->clone_with_increased_indirection()))) {
add_after_in(ast_statement_ptr(make_method_call(backing.identifier, "copy_construct", vector(make_operator_call("&", vector(backing.expression))))),
var temp_cpy_ctst = ast_identifier_ptr("temp_declaration_copy_construct", get_ast_type(backing.expression)->clone_without_ref(), null<ast_node>())
var declaration = ast_statement_ptr(ast_declaration_statement_ptr(temp_cpy_ctst, backing.expression, false))
add_after_in(ast_statement_ptr(make_method_call(backing.identifier, "copy_construct", vector(make_operator_call("&", vector(temp_cpy_ctst))))),
parent_chain->top(), parent_chain->from_top(1))
// do second so the order's right
add_after_in(declaration,
parent_chain->top(), parent_chain->from_top(1))
backing.expression = null<ast_node>()
}

View File

@@ -1,6 +1,6 @@
import io
import string
import ast_transformation
import util
import vector
import string
import mem
@@ -151,7 +151,7 @@ obj regex (Object, Serializable) {
var perenEnd = i + 1
for (var depth = 1; depth > 0; perenEnd++;) {
if (perenEnd >= regex_string.length())
ast_transformation::error(string::string("can't find matching peren in: ") + regex_string)
util::error(string::string("can't find matching peren in: ") + regex_string)
// be careful, this isn't quite right yet
/*var not_non_special = perenEnd == 0 || (regex_string[perenEnd-1] != '\\' && regex_string[perenEnd-1] != '[' && (perenEnd+1 >= regex_string.length() || regex_string[perenEnd+1] != ']'))*/
var not_non_special = perenEnd == 0 || (regex_string[perenEnd-1] != '[' && (perenEnd+1 >= regex_string.length() || regex_string[perenEnd+1] != ']'))

View File

@@ -41,18 +41,18 @@ fun min<T>(a: T, b: T): T {
fun hash<T(Hashable)>(item: T): ulong return item.hash()
fun hash<T>(item: *T): ulong return (item) cast ulong
fun hash(item: char): ulong return item
fun hash(item: uchar): ulong return item
fun hash(item: short): ulong return item
fun hash(item: ushort): ulong return item
fun hash(item: int): ulong return item
fun hash(item: uint): ulong return item
fun hash(item: long): ulong return item
fun hash(item: ulong): ulong return item
fun hash(item: char): ulong return (item) cast ulong
fun hash(item: uchar): ulong return (item) cast ulong
fun hash(item: short): ulong return (item) cast ulong
fun hash(item: ushort): ulong return (item) cast ulong
fun hash(item: int): ulong return (item) cast ulong
fun hash(item: uint): ulong return (item) cast ulong
fun hash(item: long): ulong return (item) cast ulong
fun hash(item: ulong): ulong return (item) cast ulong
// default hash
fun hash<T>(item: T): ulong {
io::println("using empty hash - please do not do!")
return 0
return (0) cast ulong
}
fun make_pair<T,U>(first: T, second: U): pair<T,U> {

View File

@@ -1,3 +1,4 @@
Test linear map:
3
2
1
@@ -10,6 +11,7 @@ Lookie, a map!
What I get for not testing different types
key: 7, value: Lookie, a map!
key: 30, value: we'll look for for_each too
Test hash map:
3
2
1

View File

@@ -24,9 +24,11 @@ fun test_map<T,V>(m: ref T, mapEx: ref V) {
mapEx.for_each(fun(key:int, value:*char) { print("key: "); print(key); print(", value: "); println(value); })
}
fun main(): int {
println("Test linear map:")
var m1 = map(3,1)
var mapEx1 = map(7, "Lookie, a map!")
test_map(m1, mapEx1)
println("Test hash map:")
var m2 = hash_map(3,1)
var mapEx2 = hash_map(7, "Lookie, a map!")
test_map(m2, mapEx2)