Skip to content

Commit

Permalink
Merge pull request #48 from Princess-org/polymorph
Browse files Browse the repository at this point in the history
Polymorph
  • Loading branch information
Victorious3 authored Apr 15, 2024
2 parents 34df294 + 2b25522 commit 2daae03
Show file tree
Hide file tree
Showing 12 changed files with 343 additions and 217 deletions.
7 changes: 2 additions & 5 deletions src/codegen.pr
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ def type_to_str(tpe: &typechecking::Type) -> Str {
ret = "null"
case typechecking::TypeKind::STUB
ret = "%\"" + tpe.type_name + '"'
case typechecking::TypeKind::INTERFACE_IMPL
ret = type_to_str(tpe.tpe)
case typechecking::TypeKind::TO_INFER
ret = "<?>"
case typechecking::TypeKind::GENERIC
ret = "<ERROR>"
case
error(debug::type_to_str(tpe), " ", typechecking::is_polymorph(tpe), "\n")
error(tpe.kind, "\n")
Expand Down Expand Up @@ -254,9 +254,6 @@ def value_to_str(value: compiler::Value) -> Str {
def named_parameter_to_str(named: typechecking::NamedParameter) -> Str {
var ret: StringBuffer = ""
var tpe = named.tpe
if tpe and tpe.kind == typechecking::TypeKind::INTERFACE_IMPL {
tpe = tpe.tpe
}
if named.varargs {
if tpe {
ret += "{i" + (size_of size_t) * 8 + ", " + type_to_str(tpe) + "*}"
Expand Down
43 changes: 16 additions & 27 deletions src/compiler.pr
Original file line number Diff line number Diff line change
Expand Up @@ -2811,16 +2811,6 @@ def insert_call(
node: &parser::Node, name_v: Value, args: &[Value], proto: &[typechecking::NamedParameter], ret: &typechecking::Type,
varargs_loc: &Vector(&Value), addr: Value, loc: &Value,
multiple_returns: bool, state: &State) {

for var i in 0..args.size {
if i >= proto.size { continue }
// Replace interfaces in proto with the actual type
let np = proto(i)
if np._tpe and np._tpe.kind == typechecking::TypeKind::STRUCTURAL {
np._tpe = typechecking::make_interface_impl(np._tpe, args(i).tpe, state.scope)
proto(i) = np
}
}

let value = state.call(name_v, ret, args, node.value.func_call.inline, proto, loc)

Expand Down Expand Up @@ -3218,7 +3208,18 @@ def walk_Identifier(node: &parser::Node, state: &State) -> Value {

import_structures(tpe, state.module)
if (@val).global {
(@(@state).module).imported.add((@val).assembly_name(state))
let name = val.assembly_name(state)
(@(@state).module).imported.add(name)
if val.module != state.module and
not is_function(val.tpe) and
not state.module.result.globals.contains(name) {

state.module.result.globals(name) = [
tpe = val.tpe,
name = name,
external = true
] !&Global
}
}

if (@val).value {
Expand Down Expand Up @@ -5923,7 +5924,7 @@ def walk_Defer(node: &parser::Node, state: &State) {
_tpe = typechecking::pointer(current_function.env)
] !typechecking::NamedParameter)

let tpe = typechecking::make_function_type_n(parser::make_identifier("defer"), parameter_t, vector::make(type &typechecking::Type))
let tpe = typechecking::make_function_type_n(parser::make_identifier("defer"), parameter_t, vector::make(type &typechecking::Type), context = state.module)

let keys_locals = map::keys(current_function.locals)

Expand Down Expand Up @@ -6615,10 +6616,6 @@ def di_type(tpe: &typechecking::Type, state: &State) -> &Value {
name = "<anonymous>"
}

if tpe.kind == typechecking::TypeKind::INTERFACE_IMPL {
return di_type(tpe.tpe, state)
}

ditpe = [] !&Value
let ditpep = push_meta(ditpe, state)
(@state).ditypes(tpe) = ditpep
Expand Down Expand Up @@ -6787,7 +6784,7 @@ def defer_unroll(node: &parser::Node, state: &State) {
_tpe = typechecking::pointer(state.current_function.env)
] !typechecking::NamedParameter)

let tpe = typechecking::make_function_type_n(parser::make_identifier("defer"), parameter_t, vector::make(type &typechecking::Type))
let tpe = typechecking::make_function_type_n(parser::make_identifier("defer"), parameter_t, vector::make(type &typechecking::Type), context = state.module)

let br_to_start = make_insn(InsnKind::BR_UNC)
push_insn(br_to_start, state)
Expand Down Expand Up @@ -7416,9 +7413,6 @@ export def create_function(
for var i in 0..vector::length(function.args) {
let np = function.args(i)
var value = np.tpe
if value and value.kind == typechecking::TypeKind::INTERFACE_IMPL {
value = value.tpe
}
if np.varargs and value {
value = typechecking::array(value)
}
Expand Down Expand Up @@ -7588,9 +7582,8 @@ export def create_function(
let return_t = vector::make(type &typechecking::Type)
return_t.push(function.optional)
let impl_tpe = typechecking::make_function_type_n(parser::make_identifier(tpe.name + ".impl"),
parameter_t, return_t, state.module
parameter_t, return_t, state.module, context = state.module
)
impl_tpe.type_name = typechecking::mangle_function_name(impl_tpe.name, tpe.parameter_t)

state.store(
[ kind = ValueKind::LOCAL, tpe = pointer(builtins::int_), name = "__block" ] !Value,
Expand Down Expand Up @@ -7633,9 +7626,8 @@ export def create_function(
let parameter_t2 = vector::make(typechecking::NamedParameter)
parameter_t2.push([ name = "__context", _tpe = typechecking::pointer(null) ] !typechecking::NamedParameter)
let free_context_tpe = typechecking::make_function_type_n(parser::make_identifier(tpe.name + ".free_context"),
free_context_parameters, vector::make(type &typechecking::Type), state.module
free_context_parameters, vector::make(type &typechecking::Type), state.module, context = state.module
)
free_context_tpe.type_name = typechecking::mangle_function_name(free_context_tpe.name, tpe.parameter_t)

let free_context = predeclare_function(free_context_tpe, state.module)
free_context.is_compiled = true
Expand Down Expand Up @@ -8896,9 +8888,6 @@ def do_create_type(tpe: &typechecking::Type, svalue: &scope::Value, module: &too
if tpe.kind == typechecking::TypeKind::BOX {
tpe = tpe.weak
}
if tpe.kind == typechecking::TypeKind::INTERFACE_IMPL {
tpe = tpe.tpe
}

let generic = typechecking::get_generic(tpe)
if generic and generic.tc_incomplete { return null }
Expand Down
12 changes: 10 additions & 2 deletions src/consteval.pr
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ export def walk_Def(node: &parser::Node, state: &typechecking::State) {
let impl = node.value.def_.impl
let has_yield = node.value.def_.has_yield

//let prev_context = state.context
//state.context = state.module.scope
//defer state.context = prev_context

var body = node.value.def_.body
let imported = (share !int & parser::ShareMarker::IMPORT !int) != 0
let exported = (share !int & parser::ShareMarker::EXPORT !int) != 0
Expand Down Expand Up @@ -439,9 +443,10 @@ export def walk_Def(node: &parser::Node, state: &typechecking::State) {
let type_constructor = typechecking::get_type_constructor(first_param.tpe)
if type_constructor and type_constructor.cache {
let type_name = debug::type_to_str(first_param.tpe, full_name = true)
if not map::contains(type_constructor.cache, type_name) {
let ref = [module = state.get_context(), name = type_name] !typechecking::TypeRef
if not map::contains(type_constructor.cache, ref) {
typechecking::generate_concrete_functions(type_constructor, first_param.tpe, state)
type_constructor.cache(type_name) = first_param.tpe
type_constructor.cache(ref) = first_param.tpe
}
}
}
Expand Down Expand Up @@ -805,7 +810,10 @@ export def compile_function(value: &scope::Value, context: &scope::Scope, argume
const_module.result.functions(function.name) = function
} else {
walk_Def(node, state)
let prev_context = state.context
state.context = node.scope
typechecking::walk_Def(node, state)
state.context = prev_context
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/debug.pr
Original file line number Diff line number Diff line change
Expand Up @@ -884,8 +884,6 @@ export def type_to_str(tpe: &typechecking::Type, full_name: bool = false) -> Str
return generic_t_to_string(tpe, full_name)
case typechecking::TypeKind::TUNION, typechecking::TypeKind::VARIANT
return variant_t_to_string(tpe, full_name)
case typechecking::TypeKind::INTERFACE_IMPL
return type_to_str(tpe.tpe, full_name) + "/" + type_to_str(tpe.intf, full_name) + "#" + tpe.module.module
case typechecking::TypeKind::TO_INFER
return "<?>"
case
Expand Down
9 changes: 9 additions & 0 deletions src/errors.pr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import compiler
import map
import parser
import progress
import toolchain

export var error_count = 0
export var suppress_errors = false
Expand Down Expand Up @@ -120,6 +121,10 @@ export def errorn(node: &parser::Node, msg: String...) {
message = message
] !Diagnostic
error_handler(diagnostic)

if toolchain::exit_on_first_error {
abort("Compilation failure\n")
}
}

export def errort(token: lexer::Token, state: &parser::ParseState, msg: String...) {
Expand Down Expand Up @@ -150,5 +155,9 @@ export def errort(token: lexer::Token, state: &parser::ParseState, msg: String..
] !Diagnostic
error_handler(diagnostic)

if toolchain::exit_on_first_error {
abort("Compilation failure\n")
}

state.has_error = true
}
2 changes: 2 additions & 0 deletions src/main.pr
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ let options = [
.set_help("Compile without importing std")),
(option(*toolchain::trace_consteval, "--trace-consteval")
.set_help("Trace code generated for consteval")),
(option(*toolchain::exit_on_first_error, "--exit-on-first-error")
.set_help("Abort compilation on first error")),
(option(*filename, "compile")
.set_help("File to compile")
.set_metavar("FILE"))
Expand Down
2 changes: 1 addition & 1 deletion src/parser.pr
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ export let invalid_loc: SourceLoc = [
] !SourceLoc

export def is_invalid(loc: SourceLoc) -> bool {
return loc.filename == null
return not to_bool(loc.filename)
}

export def == (this: SourceLoc, other: SourceLoc) -> bool {
Expand Down
Loading

0 comments on commit 2daae03

Please sign in to comment.