Skip to content

Commit

Permalink
Fix reference types
Browse files Browse the repository at this point in the history
  • Loading branch information
Victorious3 committed Apr 3, 2022
1 parent 3ae68fc commit 90dac39
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 65 deletions.
124 changes: 61 additions & 63 deletions src/compiler.pr
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export def store(state: *State, vloc: Value, value: Value, loc: *Value) {
store.value.store = {
loc = vloc,
value = value
}
} !InsnStore
push_insn(store, state)
}

Expand All @@ -244,6 +244,22 @@ export type InsnLoad = struct {
loc: Value
}

export def load(state: *State, tpe: *typechecking::Type, locv: Value) -> Value {
return load(state, tpe, locv, null)
}

export def load(state: *State, tpe: *typechecking::Type, locv: Value, loc: *Value) -> Value {
let load_ret = make_local_value(tpe, null, state)
let load = make_insn_dbg(InsnKind::LOAD, loc)
load.value.load = {
loc = locv,
value = load_ret
} !InsnLoad
push_insn(load, state)

return load_ret
}

export def ret(state:* State, value: Value) {
ret(state, value, null)
}
Expand Down Expand Up @@ -1091,7 +1107,36 @@ export def convert_to(node: *parser::Node, value: Value, tpe: *typechecking::Typ
}

var kind: InsnKind
if typechecking::is_ref(tpe) and (typechecking::is_assignable(tpe.tpe, value.tpe, state.module) or
if typechecking::is_ref(tpe) and typechecking::is_ref(value.tpe) {
return convert_ref_to_ref(tpe, value, loc, state)
} else if typechecking::is_ref(tpe) and typechecking::equals(value.tpe, builtins::Ref_) {
return convert_ref_to_ref(tpe, value, loc, state)
} else if typechecking::equals(tpe, builtins::Ref_) and typechecking::is_ref(value.tpe) {
return convert_ref_to_ref(tpe, value, loc, state)
} else if typechecking::is_pointer(tpe) and typechecking::is_ref(value.tpe) {

let index = allocate(int, 1)
index[0] = 1
let extract_ret = make_local_value(typechecking::pointer(value.tpe.tpe), null, state)
let extract = make_insn_dbg(InsnKind::EXTRACTVALUE, loc)
extract.value.extract_value = {
ret = extract_ret,
value = value,
index = index
} !InsnExtractValue
push_insn(extract, state)

let bitcast_ret = make_local_value(typechecking::pointer(tpe.tpe), null, state)
let bitcast = make_insn_dbg(InsnKind::BITCAST, loc)
bitcast.value.convert = {
ret = bitcast_ret,
value = extract_ret
} !InsnConvert
push_insn(bitcast, state)

return bitcast_ret

} else if typechecking::is_ref(tpe) and (typechecking::is_assignable(tpe.tpe, value.tpe, state.module) or
typechecking::is_assignable(tpe, typechecking::reference(value.tpe), state.module) or
tpe.tpe == null or value.tpe.kind == typechecking::TypeKind::NULL) {

Expand All @@ -1102,7 +1147,7 @@ export def convert_to(node: *parser::Node, value: Value, tpe: *typechecking::Typ
}

map::put(state.module.imported, "malloc", map::sentinel)
let svalue = do_create_type(value.tpe, state.module)
let svalue = do_create_type(typechecking::reference(value.tpe), state.module)

let args1 = allocate(Value, 1)
args1[0] = { kind = ValueKind::INT, tpe = builtins::int64_, i = builtins::int64_.size } !Value
Expand Down Expand Up @@ -1211,35 +1256,6 @@ export def convert_to(node: *parser::Node, value: Value, tpe: *typechecking::Typ
push_insn(insert3, state)

return ret_insert3
} else if typechecking::is_ref(tpe) and typechecking::is_ref(value.tpe) {
return convert_ref_to_ref(tpe, value, loc, state)
} else if typechecking::is_ref(tpe) and typechecking::equals(value.tpe, builtins::Ref_) {
return convert_ref_to_ref(tpe, value, loc, state)
} else if typechecking::equals(tpe, builtins::Ref_) and typechecking::is_ref(value.tpe) {
return convert_ref_to_ref(tpe, value, loc, state)
} else if typechecking::is_pointer(tpe) and typechecking::is_ref(value.tpe) {

let index = allocate(int, 1)
index[0] = 1
let extract_ret = make_local_value(typechecking::pointer(value.tpe.tpe), null, state)
let extract = make_insn_dbg(InsnKind::EXTRACTVALUE, loc)
extract.value.extract_value = {
ret = extract_ret,
value = value,
index = index
} !InsnExtractValue
push_insn(extract, state)

let bitcast_ret = make_local_value(typechecking::pointer(tpe.tpe), null, state)
let bitcast = make_insn_dbg(InsnKind::BITCAST, loc)
bitcast.value.convert = {
ret = bitcast_ret,
value = extract_ret
} !InsnConvert
push_insn(bitcast, state)

return bitcast_ret

} else if tpe.kind == typechecking::TypeKind::ARRAY {
if (@value.tpe).kind == typechecking::TypeKind::STATIC_ARRAY and
(@value.tpe).length == 0 {
Expand Down Expand Up @@ -3553,32 +3569,13 @@ def walk_IfExpr(node: *parser::Node, state: *State) -> Value {
return { kind = ValueKind::LOCAL, tpe = if_true.tpe, addr = addrp } !Value
}

def walk_PtrT(node: *parser::Node, state: *State) -> Value {
let expr = node.value.t_parr.tpe
node.svalue = change_value_to_type(node.tpe.tpe, state)
if not node.svalue { return NO_VALUE }
return @node.svalue.value
}

def walk_ArrayT(node: *parser::Node, state: *State) -> Value {
def walk_Type(node: *parser::Node, state: *State) -> Value {
let expr = node.value.t_parr.tpe
node.svalue = change_value_to_type(node.tpe.tpe, state)
if not node.svalue { return NO_VALUE }
return @node.svalue.value
}

def walk_ArrayStaticT(node: *parser::Node, state: *State) -> Value {
let expr = node.value.t_parr.tpe
node.svalue = change_value_to_type(node.tpe.tpe, state)
if not node.svalue { return NO_VALUE }
return @node.svalue.value
}

// TODO implement this
def walk_FunctionT(node: *parser::Node, state: *State) -> Value {
return NO_VALUE
}

def walk_TypeOfT(node: *parser::Node, state: *State) -> Value {
let expr = node.value.expr
node.svalue = change_value_to_type(expr.tpe, state)
Expand Down Expand Up @@ -3665,14 +3662,9 @@ export def walk_expression(node: *parser::Node, state: *State) -> Value {
return walk_StructLit(node, state)
case parser::NodeKind::ARRAY_LIT:
return walk_ArrayLit(node, state)
case parser::NodeKind::ARRAY_STATIC_T:
return walk_ArrayStaticT(node, state)
case parser::NodeKind::PTR_T:
return walk_PtrT(node, state)
case parser::NodeKind::ARRAY_T:
return walk_ArrayT(node, state)
case parser::NodeKind::FUNCTION_T:
return walk_FunctionT(node, state)
case parser::NodeKind::ARRAY_STATIC_T, parser::NodeKind::PTR_T,
parser::NodeKind::REF_T, parser::NodeKind::ARRAY_T, parser::NodeKind::FUNCTION_T:
return walk_Type(node, state)
case parser::NodeKind::TYPE_OF_T:
return walk_TypeOfT(node, state)
case parser::NodeKind::IF_EXPR:
Expand Down Expand Up @@ -4272,7 +4264,7 @@ def push_ref_init(value: Value, loc: *Value, state: *State) {
map::put(state.module.imported, "malloc", map::sentinel)
let ref_tpe = value.tpe.tpe.tpe

let svalue = do_create_type(ref_tpe, state.module)
let svalue = do_create_type(value.tpe.tpe, state.module)

let args = allocate(Value, 1)
args[0] = make_int_value(builtins::int64_.size !int)
Expand Down Expand Up @@ -6527,11 +6519,17 @@ def generate_vtable_function(function: *Function, tpe: *typechecking::Type, stat
map::put(state.module.imported, equals.tpe.type_name, map::sentinel)

// Extract type
let tpe_value = state.extract_value(
let ref_tpe = state.extract_value(
typechecking::pointer(builtins::Type_),
{ kind = ValueKind::LOCAL, tpe = first_param, name = "__ref.value"} !Value,
[2]
)
)
let ref_tpe_deref = state.load(builtins::Type_, ref_tpe)
let tpe_value = state.extract_value(
typechecking::pointer(builtins::Type_),
ref_tpe_deref,
[4]
)

let keys = map::keys(typechecking::types_map)
for var i in 0..keys.size {
Expand Down
2 changes: 1 addition & 1 deletion src/scope.pr
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def find_function(scope: *Scope, node: *parser::Node, v: *Value, parameter_t: *v
first_parameter.name = "__ref"

if first_parameter.tpe.kind == typechecking::TypeKind::REFERENCE and
(not first_parameter.tpe.tpe or first_parameter.tpe.tpe.kind == typechecking::TypeKind::STRUCTURAL) {
(first_parameter.tpe.tpe and first_parameter.tpe.tpe.kind == typechecking::TypeKind::STRUCTURAL) {

let equals = get(toolchain::runtime.scope, parser::make_identifier(["equals"]))
consteval::compile_function(equals.node, equals.state)
Expand Down
11 changes: 11 additions & 0 deletions src/typechecking.pr
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,15 @@ def walk_PtrT(node: *parser::Node, state: *State) {
node.tpe = pointer(tpe2)
}

def walk_RefT(node: *parser::Node, state: *State) {
let expr = node.value.t_parr.tpe
walk(node, expr, state)
let tpe = expr.svalue.value.value_tpe
let tpe2 = copy(builtins::Type_)
tpe2.tpe = reference(tpe, node.value.t_parr.kw)
node.tpe = pointer(tpe2)
}

def walk_ArrayT(node: *parser::Node, state: *State) {
let expr = node.value.t_parr.tpe
walk(node, expr, state)
Expand Down Expand Up @@ -2959,6 +2968,8 @@ export def walk(parent: *parser::Node, node: *parser::Node, state: *State) {
walk_Assert(node, state)
case parser::NodeKind::PTR_T:
walk_PtrT(node, state)
case parser::NodeKind::REF_T:
walk_RefT(node, state)
case parser::NodeKind::ARRAY_T:
walk_ArrayT(node, state)
case parser::NodeKind::ARRAY_STATIC_T:
Expand Down
2 changes: 1 addition & 1 deletion std/std.pr
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export def fprint(file: File, args: &...) -> int {
var sum = 0
for var i in 0..args.size {
let arg = args[i]
sum += print_val(file, runtime::ref_type(arg), arg !*)
sum += print_val(file, runtime::ref_type(arg).tpe, arg !*)
}
return sum
}
Expand Down

0 comments on commit 90dac39

Please sign in to comment.