Skip to content

Commit

Permalink
Simplify name mangling, create varargs
Browse files Browse the repository at this point in the history
  • Loading branch information
Victorious3 committed Jun 30, 2021
1 parent 8c8ad82 commit 835ba10
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 102 deletions.
2 changes: 1 addition & 1 deletion src/builtin_functions.pr
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ def print_enum(node: *parser::Node, values: *vector::Vector, value: *compiler::V
(@call).value.call = {
name = {
kind = compiler::ValueKind::GLOBAL,
name = typechecking::mangle_function_name(type_name, parameter_t)
name = type_name
} !compiler::Value,
ret = ret,
args = args
Expand Down
7 changes: 6 additions & 1 deletion src/builtins.pr
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export let float_ = create_float_type("float", size_of float)
export let double_ = create_float_type("double", size_of double)
export let float32_ = create_float_type("float32", size_of float32)
export let float64_ = create_float_type("float64", size_of float64)
// TODO use size_of
export let float80_ = create_float_type("float80", 16)

export let byte_ = create_int_type("byte", size_of byte, false)
export let short_ = create_int_type("short", size_of short, false)
Expand Down Expand Up @@ -86,6 +88,10 @@ let file_t = typechecking::make_type(typechecking::TypeKind::STRUCT, parser::mak
export let File_ = typechecking::pointer(file_t)
scope::create_type(builtins, parser::make_identifier(["File"]), parser::ShareMarker::NONE, File_)

let va_list_ident = parser::make_identifier(["__va_list_tag"])
export let __va_list_tag_ = typechecking::make_type(typechecking::TypeKind::STRUCT, va_list_ident)
scope::create_type(builtins, va_list_ident, parser::ShareMarker::NONE, __va_list_tag_)

scope::create_variable(builtins, parser::make_identifier(["stdin"]), parser::ShareMarker::NONE, parser::VarDecl::VAR, File_, null)
scope::create_variable(builtins, parser::make_identifier(["stdout"]), parser::ShareMarker::NONE, parser::VarDecl::VAR, File_, null)
scope::create_variable(builtins, parser::make_identifier(["stderr"]), parser::ShareMarker::NONE, parser::VarDecl::VAR, File_, null)
Expand All @@ -95,7 +101,6 @@ scope::create_variable(builtins, parser::make_identifier(["PATH_MAX"]), parser::
let win32: bool = WIN32
scope::create_variable(builtins, parser::make_identifier(["WIN32"]), parser::ShareMarker::NONE, parser::VarDecl::CONST, bool_, *win32)

//scope::create_variable(builtins, parser::make_identifier(["args"]), parser::ShareMarker::NONE, parser::VarDecl::LET, typechecking::array(string_), null)

export let array = typechecking::make_type(typechecking::TypeKind::STRUCT, parser::make_identifier(["Array"]))
(@array).fields = allocate(typechecking::StructMember, 2)
Expand Down
13 changes: 12 additions & 1 deletion src/codegen.pr
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ def type_to_str(tpe: *typechecking::Type) -> string {
buffer::append_char(*buf, 'i')
buffer::append_str(*buf, util::int_to_str((@tpe).size * 8))
case typechecking::TypeKind::FLOAT:
// TODO We might want to support float128 as a different type
switch (@tpe).size {
case 4: buffer::append_str(*buf, "float")
case 8: buffer::append_str(*buf, "double")
case 16: buffer::append_str(*buf, "x86_fp80")
case: assert(false)
}
case typechecking::TypeKind::POINTER:
Expand Down Expand Up @@ -98,6 +100,10 @@ def type_to_str(tpe: *typechecking::Type) -> string {
buffer::append_str(*buf, ")")
case typechecking::TypeKind::NULL:
buffer::append_str(*buf, "null")
case typechecking::TypeKind::STUB:
buffer::append_str(*buf, "%\"")
buffer::append_str(*buf, (@tpe).type_name)
buffer::append_char(*buf, '"')
case:
error((@tpe).kind, "\n")
assert(false)
Expand Down Expand Up @@ -559,7 +565,12 @@ def emit_function(fp: File, function: *compiler::Function) {
let tpe = (@np).value
let name = (@np).name

write_string(fp, type_to_str(tpe))
if (@np).varargs {
write_string(fp, "...")
} else {
write_string(fp, type_to_str(tpe))
}

if not (@function).forward_declare {
write_string(fp, " ")
write_string(fp, "%", name)
Expand Down
40 changes: 25 additions & 15 deletions src/compiler.pr
Original file line number Diff line number Diff line change
Expand Up @@ -1658,6 +1658,7 @@ def walk_Call(node: *parser::Node, state: *State) -> Value {
return (@tpe).macro(node, args, state)
}

var proto = [] ![NamedParameter]
var name_v: Value
var ret: *typechecking::Type = null
if is_fp {
Expand All @@ -1669,12 +1670,17 @@ def walk_Call(node: *parser::Node, state: *State) -> Value {
name_v = walk_expression((@node).value.func_call.left, state)
} else {
var name = (@tpe).type_name
name = typechecking::mangle_function_name(name, parameter_t)

let function = map::get((@(@state).result).functions, name) !*Function
if not function { return NO_VALUE }
ret = (@function).ret

let len = vector::length((@function).args)
proto = allocate(NamedParameter, len)
for var i in 0..len {
proto[i] = @(vector::get((@function).args, i) !*NamedParameter)
}

name_v = {
kind = ValueKind::GLOBAL,
name = name
Expand Down Expand Up @@ -1702,7 +1708,8 @@ def walk_Call(node: *parser::Node, state: *State) -> Value {
(@insn).value.call = {
name = name_v,
ret = value,
args = args
args = args,
proto = proto
} !InsnCall

push_insn(insn, state)
Expand Down Expand Up @@ -1753,7 +1760,7 @@ def walk_Identifier(node: *parser::Node, state: *State) -> Value {
push_insn(insn, state)
return value
} else {
(@locv).name = typechecking::mangle_function_name((@tpe).type_name, (@tpe).parameter_t)
(@locv).name = (@tpe).type_name
let value = {
kind = ValueKind::LOCAL,
name = name,
Expand Down Expand Up @@ -3511,8 +3518,8 @@ def create_function(node: *parser::Node, tpe: *typechecking::Type, body: *vector
if node { line = (@node).loc.line }

let function = allocate(Function)
(@function).name = typechecking::mangle_function_name((@tpe).type_name, (@tpe).parameter_t)
(@function).unmangled = (@tpe).type_name
(@function).name = (@tpe).type_name
(@function).unmangled = (@tpe).name
(@function).multiple_returns = false
(@function).forward_declare = true
(@function).debug = null
Expand Down Expand Up @@ -3711,7 +3718,7 @@ def walk_TypeDecl(node: *parser::Node, state: *State) {

let function = allocate(Function)
@function = {
name = typechecking::mangle_function_name(type_name, parameter_t),
name = type_name,
unmangled = type_name,
args = parameter_t,
ret = builtins::string_
Expand Down Expand Up @@ -3772,16 +3779,24 @@ def walk_TypeDecl(node: *parser::Node, state: *State) {

def walk_top_VarDecl(node: *parser::Node, body: *vector::Vector, state: *State) {
let left = vector::make()
let share = (@node).value.var_decl.share

var external = false
if share !int & parser::ShareMarker::IMPORT !int {
external = true
}

for var i in 0..vector::length((@node).value.var_decl.left) {
let n = vector::get((@node).value.var_decl.left, i) !*parser::Node
if (@n).kind == parser::NodeKind::ID_DECL {
let v = (@n).value.id_decl.value
let value = scope::get((@node).scope, v)
if not value { continue }
let name = (@value).assembly_name

let global = allocate(Global)
@global = {
external = external,
name = name,
tpe = (@v).tpe,
line = (@v).loc.line
Expand Down Expand Up @@ -4062,10 +4077,9 @@ export def compile(module: *toolchain::Module) -> *Result {
(@ident).loc.filename = (@module).filename
(@ident).loc.line = 0
(@ident).loc.column = 0
let main_tpe = typechecking::make_type(typechecking::TypeKind::FUNCTION, ident)


let string_array_tpe = typechecking::array(builtins::string_)

let named = allocate(typechecking::NamedParameter)
(@named).name = "args"
(@named).value = string_array_tpe
Expand All @@ -4074,11 +4088,7 @@ export def compile(module: *toolchain::Module) -> *Result {
let args = vector::make()
vector::push(args, named)

(@main_tpe).parameter_t = args
// TODO Infer return types
(@main_tpe).return_t = vector::make()
(@main_tpe).macro = null
(@main_tpe).proto = null
let main_tpe = typechecking::make_function_type_n(ident, args, vector::make())

scope::create_function((@node).scope, ident, parser::ShareMarker::EXPORT, main_tpe, false)

Expand Down
5 changes: 4 additions & 1 deletion src/lexer.pr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type TokenType = enum {
C_SQUARE
OP_RANGE
OP_RANGE_INC
OP_VARARGS
OP_CAST
OP_AUTOCAST
OP_DEREF
Expand Down Expand Up @@ -695,7 +696,7 @@ def parse_pragma(s: string, i: *int, line: *int, column: *int) -> Token {

var buf = buffer::make_buffer()
var c = peek_char(s, i, 0)
while c == '#' or is_text(c) {
while c == '#' or is_text(c) or is_alphanumeric(c) {
buffer::append_char(*buf, c)
c = next_char(s, i, line, column)
}
Expand Down Expand Up @@ -729,6 +730,8 @@ def parse_symbol(s: string, i: *int, line: *int, column: *int) -> Token {
tt = TokenType::OP_PSUB_EQ
} else if first == '.' and second == '.' and third == '=' {
tt = TokenType::OP_RANGE_INC
} else if first == '.' and second == '.' and third == '.' {
tt = TokenType::OP_VARARGS
} else {
length = 2
if second == '=' {
Expand Down
107 changes: 78 additions & 29 deletions src/parser.pr
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export type VarDecl = enum {
export type Node

export type NodeDef = struct {
extern: bool
share: ShareMarker
name: *Node
params: *vector::Vector
Expand All @@ -121,6 +122,7 @@ export type NodeDef = struct {
}

export type NodeParam = struct {
varargs: bool
kw: VarDecl
name: *Node
tpe: *Node
Expand Down Expand Up @@ -176,6 +178,7 @@ export type NodeIdDecl = struct {
}

export type NodeVarDecl = struct {
extern: bool
share: ShareMarker
kw: VarDecl
left: *vector::Vector
Expand Down Expand Up @@ -1486,13 +1489,28 @@ def expect_expression_no_assign(parse_state: *ParseState) -> *Node {
return node
}

// TODO Make sure varargs can only be in the last position
def parse_def(parse_state: *ParseState, share: ShareMarker) -> *Node {
var token = peek(parse_state)
let line = token.line
let column = token.column

expect(parse_state, lexer::TokenType::K_DEF, "Expected def\n")
skip_newline(parse_state)

token = peek(parse_state)
var extern = false
while token.tpe == lexer::TokenType::PRAGMA {
pop(parse_state)
if token.value.str == "#extern" {
extern = true
} else {
errort(token, parse_state, "Invalid pragma\n")
}
skip_newline(parse_state)
token = peek(parse_state)
}

let name = expect_identifier(parse_state)
//skip_newline(parse_state)
var params = vector::make()
Expand All @@ -1508,42 +1526,58 @@ def parse_def(parse_state: *ParseState, share: ShareMarker) -> *Node {
let line = token.line
let column = token.column

var varargs = false
var kw = VarDecl::VAR
if token.tpe == lexer::TokenType::K_LET {
kw = VarDecl::LET
pop(parse_state)
} else if token.tpe == lexer::TokenType::K_VAR {
kw = VarDecl::VAR
pop(parse_state)
} else if token.tpe == lexer::TokenType::K_TYPE {
kw = VarDecl::TYPE
pop(parse_state)
}

skip_newline(parse_state)
let name = expect_identifier(parse_state)
skip_newline(parse_state)
var name: *Node = null
var tpe: *Node = null
token = peek(parse_state)
if token.tpe == lexer::TokenType::COLON {
pop(parse_state)
tpe = expect_type(parse_state)
}

skip_newline(parse_state)
token = peek(parse_state)
var value: *Node = null
if token.tpe == lexer::TokenType::OP_ASSIGN {

if token.tpe == lexer::TokenType::OP_VARARGS {
varargs = true
pop(parse_state)
if kw == VarDecl::TYPE {
value = expect_type(parse_state)
} else {
value = expect_expression_no_assign(parse_state)
} else {
if token.tpe == lexer::TokenType::K_LET {
kw = VarDecl::LET
pop(parse_state)
} else if token.tpe == lexer::TokenType::K_VAR {
kw = VarDecl::VAR
pop(parse_state)
} else if token.tpe == lexer::TokenType::K_TYPE {
kw = VarDecl::TYPE
pop(parse_state)
}

skip_newline(parse_state)
name = expect_identifier(parse_state)
skip_newline(parse_state)

token = peek(parse_state)
if token.tpe == lexer::TokenType::COLON {
pop(parse_state)
tpe = expect_type(parse_state)
token = peek(parse_state)
if token.tpe == lexer::TokenType::OP_VARARGS {
pop(parse_state)
varargs = true
}
}

skip_newline(parse_state)
token = peek(parse_state)

if token.tpe == lexer::TokenType::OP_ASSIGN {
pop(parse_state)
if kw == VarDecl::TYPE {
value = expect_type(parse_state)
} else {
value = expect_expression_no_assign(parse_state)
}
}
}
var param = make_node(NodeKind::PARAMETER, line, column, parse_state)

let param = make_node(NodeKind::PARAMETER, line, column, parse_state)
(@param).value.param = {
varargs = varargs,
kw = kw,
name = name,
tpe = tpe,
Expand Down Expand Up @@ -1600,6 +1634,7 @@ def parse_def(parse_state: *ParseState, share: ShareMarker) -> *Node {

var node = make_node(NodeKind::DEF, line, column, parse_state)
(@node).value.def_ = {
extern = extern,
share = share,
name = name,
params = params,
Expand All @@ -1621,6 +1656,19 @@ def parse_vardecl(parse_state: *ParseState, share: ShareMarker, vardecl: VarDecl
return null
}
skip_newline(parse_state)
tok = peek(parse_state)

var extern = false
while tok.tpe == lexer::TokenType::PRAGMA {
pop(parse_state)
if tok.value.str == "#extern" {
extern = true
} else {
errort(tok, parse_state, "Invalid pragma\n")
}
skip_newline(parse_state)
tok = peek(parse_state)
}

var vec_left = vector::make()
loop {
Expand Down Expand Up @@ -1695,6 +1743,7 @@ def parse_vardecl(parse_state: *ParseState, share: ShareMarker, vardecl: VarDecl

var node = make_node(NodeKind::VAR_DECL, line, column, parse_state)
(@node).value.var_decl = {
extern = extern,
share = share,
kw = vardecl,
left = vec_left,
Expand Down
Loading

0 comments on commit 835ba10

Please sign in to comment.