mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: increase support for ast.Alias
and ast.TypeOf
(#18722)
This commit is contained in:
parent
015ccc2a7f
commit
ee429bb51d
@ -112,11 +112,6 @@ fn (mut c Amd64) dec(reg Amd64Register) {
|
||||
c.g.println('dec ${reg}')
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn byt(n int, s int) u8 {
|
||||
return u8((n >> (s * 8)) & 0xff)
|
||||
}
|
||||
|
||||
fn (mut c Amd64) inc(reg Amd64Register) {
|
||||
c.g.write8(0x48)
|
||||
c.g.write8(0xff)
|
||||
@ -1009,6 +1004,7 @@ fn (mut c Amd64) push(reg Amd64Register) {
|
||||
}
|
||||
c.is_16bit_aligned = !c.is_16bit_aligned
|
||||
c.g.println('push ${reg}')
|
||||
c.g.stack_depth++
|
||||
}
|
||||
|
||||
pub fn (mut c Amd64) pop(reg Amd64Register) {
|
||||
@ -1018,6 +1014,7 @@ pub fn (mut c Amd64) pop(reg Amd64Register) {
|
||||
c.g.write8(0x58 + int(reg) % 8)
|
||||
c.is_16bit_aligned = !c.is_16bit_aligned
|
||||
c.g.println('pop ${reg}')
|
||||
c.g.stack_depth--
|
||||
}
|
||||
|
||||
pub fn (mut c Amd64) sub8(reg Amd64Register, val int) {
|
||||
@ -2102,9 +2099,15 @@ fn (mut c Amd64) assign_right_expr(node ast.AssignStmt, i int, right ast.Expr, n
|
||||
ast.StructInit {
|
||||
match node.op {
|
||||
.decl_assign {
|
||||
c.g.allocate_by_type(name, right.typ)
|
||||
dest := c.g.allocate_by_type(name, right.typ)
|
||||
if right.typ.is_any_kind_of_pointer()
|
||||
|| c.g.unwrap(right.typ).is_any_kind_of_pointer() {
|
||||
c.g.expr(right)
|
||||
c.mov_reg_to_var(LocalVar{dest, ast.u64_type_idx, name}, Amd64Register.rax)
|
||||
} else {
|
||||
c.init_struct(ident, right)
|
||||
}
|
||||
}
|
||||
else {
|
||||
c.g.n_error('Unexpected operator `${node.op}`')
|
||||
}
|
||||
@ -2773,6 +2776,9 @@ fn (mut c Amd64) gen_left_value(node ast.Expr) {
|
||||
c.add(.rax, offset)
|
||||
}
|
||||
}
|
||||
ast.StructInit, ast.ArrayInit {
|
||||
c.g.expr(node)
|
||||
}
|
||||
ast.IndexExpr {} // TODO
|
||||
ast.PrefixExpr {
|
||||
if node.op != .mul {
|
||||
@ -2825,23 +2831,7 @@ fn (mut c Amd64) prefix_expr(node ast.PrefixExpr) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
|
||||
if node.op in [.logical_or, .and] {
|
||||
c.g.expr(node.left)
|
||||
label := c.g.labels.new_label()
|
||||
c.cmp_zero(Amd64Register.rax)
|
||||
jump_addr := c.cjmp(if node.op == .logical_or { .jne } else { .je })
|
||||
c.g.labels.patches << LabelPatch{
|
||||
id: label
|
||||
pos: jump_addr
|
||||
}
|
||||
c.g.expr(node.right)
|
||||
c.g.labels.addrs[label] = c.g.pos()
|
||||
return
|
||||
} else {
|
||||
c.g.expr(node.right)
|
||||
if node.left_type.is_pure_float() {
|
||||
typ := node.left_type
|
||||
fn (mut c Amd64) fp_infix_expr(node ast.InfixExpr, left_type ast.Type) {
|
||||
// optimize for ast.Ident
|
||||
match node.left {
|
||||
ast.Ident {
|
||||
@ -2865,7 +2855,7 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
|
||||
c.g.println('and eax, 0x1')
|
||||
}
|
||||
.gt, .lt, .ge, .le {
|
||||
c.cmp_sse(.xmm0, .xmm1, typ)
|
||||
c.cmp_sse(.xmm0, .xmm1, left_type)
|
||||
// TODO mov_extend_reg
|
||||
c.mov64(Amd64Register.rax, 0)
|
||||
c.cset(match node.op {
|
||||
@ -2876,23 +2866,47 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
|
||||
})
|
||||
}
|
||||
.plus {
|
||||
c.add_sse(.xmm0, .xmm1, typ)
|
||||
c.add_sse(.xmm0, .xmm1, left_type)
|
||||
}
|
||||
.minus {
|
||||
c.sub_sse(.xmm0, .xmm1, typ)
|
||||
c.sub_sse(.xmm0, .xmm1, left_type)
|
||||
}
|
||||
.mul {
|
||||
c.mul_sse(.xmm0, .xmm1, typ)
|
||||
c.mul_sse(.xmm0, .xmm1, left_type)
|
||||
}
|
||||
.div {
|
||||
c.div_sse(.xmm0, .xmm1, typ)
|
||||
c.div_sse(.xmm0, .xmm1, left_type)
|
||||
}
|
||||
else {
|
||||
c.g.n_error('`${node.op}` expression is not supported right now')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
|
||||
if node.op in [.logical_or, .and] {
|
||||
c.g.expr(node.left)
|
||||
label := c.g.labels.new_label()
|
||||
c.cmp_zero(Amd64Register.rax)
|
||||
jump_addr := c.cjmp(if node.op == .logical_or { .jne } else { .je })
|
||||
c.g.labels.patches << LabelPatch{
|
||||
id: label
|
||||
pos: jump_addr
|
||||
}
|
||||
c.g.expr(node.right)
|
||||
c.g.labels.addrs[label] = c.g.pos()
|
||||
return
|
||||
}
|
||||
|
||||
c.g.expr(node.right)
|
||||
|
||||
left_type := c.g.unwrap(node.left_type)
|
||||
|
||||
if left_type.is_pure_float() {
|
||||
c.fp_infix_expr(node, left_type)
|
||||
return
|
||||
}
|
||||
|
||||
// optimize for ast.Ident
|
||||
match node.left {
|
||||
ast.Ident {
|
||||
@ -2911,11 +2925,13 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
|
||||
})
|
||||
}
|
||||
}
|
||||
if node.left_type !in ast.integer_type_idxs && node.left_type != ast.bool_type_idx
|
||||
&& c.g.table.sym(node.left_type).info !is ast.Enum && !node.left_type.is_ptr()
|
||||
&& !node.left_type.is_voidptr() {
|
||||
c.g.n_error('unsupported type for `${node.op}`: ${node.left_type}')
|
||||
|
||||
if left_type !in ast.integer_type_idxs && left_type != ast.bool_type_idx
|
||||
&& c.g.table.sym(left_type).info !is ast.Enum && !left_type.is_any_kind_of_pointer()
|
||||
&& node.left_type.is_any_kind_of_pointer() {
|
||||
c.g.n_error('unsupported type for `${node.op}`: ${left_type}')
|
||||
}
|
||||
|
||||
// left: rax, right: rdx
|
||||
match node.op {
|
||||
.eq, .ne, .gt, .lt, .ge, .le {
|
||||
@ -2935,7 +2951,7 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
|
||||
c.g.println('imul rax, rdx')
|
||||
}
|
||||
.div {
|
||||
if node.left_type in ast.unsigned_integer_type_idxs {
|
||||
if left_type in ast.unsigned_integer_type_idxs {
|
||||
c.g.write8(0xba)
|
||||
c.g.write32(0)
|
||||
c.g.println('mov edx, 0')
|
||||
@ -2949,7 +2965,7 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
|
||||
}
|
||||
}
|
||||
.mod {
|
||||
if node.left_type in ast.unsigned_integer_type_idxs {
|
||||
if left_type in ast.unsigned_integer_type_idxs {
|
||||
c.g.write8(0xba)
|
||||
c.g.write32(0)
|
||||
c.g.println('mov edx, 0')
|
||||
@ -2986,15 +3002,9 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Amd64) trap() {
|
||||
// funnily works on x86 and arm64
|
||||
if c.g.pref.arch == .arm64 {
|
||||
c.g.write32(0xcccccccc)
|
||||
} else {
|
||||
c.g.write8(0xcc)
|
||||
}
|
||||
c.g.println('trap')
|
||||
}
|
||||
|
||||
@ -3993,6 +4003,7 @@ fn (mut c Amd64) push_sse(reg Amd64SSERegister) {
|
||||
c.g.println('movsd [rsp], ${reg}')
|
||||
c.is_16bit_aligned = !c.is_16bit_aligned
|
||||
c.g.println('; push ${reg}')
|
||||
c.g.stack_depth++
|
||||
}
|
||||
|
||||
fn (mut c Amd64) pop_sse(reg Amd64SSERegister) {
|
||||
@ -4008,6 +4019,7 @@ fn (mut c Amd64) pop_sse(reg Amd64SSERegister) {
|
||||
c.g.println('add rsp, 0x8')
|
||||
c.is_16bit_aligned = !c.is_16bit_aligned
|
||||
c.g.println('; pop ${reg}')
|
||||
c.g.stack_depth--
|
||||
}
|
||||
|
||||
fn (mut c Amd64) gen_cast_expr(expr ast.CastExpr) {
|
||||
|
@ -385,7 +385,8 @@ fn (mut c Arm64) apicall(call ApiCall) {
|
||||
}
|
||||
|
||||
fn (mut c Arm64) trap() {
|
||||
panic('Arm64.trap() not implemented')
|
||||
c.g.write32(0xcccccccc)
|
||||
c.g.println('trap')
|
||||
}
|
||||
|
||||
fn (mut c Arm64) leave() {
|
||||
|
@ -4,6 +4,7 @@
|
||||
module native
|
||||
|
||||
import v.ast
|
||||
import v.util
|
||||
|
||||
fn (mut g Gen) expr(node ast.Expr) {
|
||||
match node {
|
||||
@ -16,54 +17,35 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), pos)
|
||||
}
|
||||
ast.BoolLiteral {
|
||||
g.code_gen.mov64(g.code_gen.main_reg(), if node.val {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
})
|
||||
g.code_gen.mov64(g.code_gen.main_reg(), int(node.val))
|
||||
}
|
||||
ast.CallExpr {
|
||||
if node.name == 'C.syscall' {
|
||||
match node.name {
|
||||
'C.syscall' {
|
||||
g.code_gen.gen_syscall(node)
|
||||
} else if node.name == 'exit' {
|
||||
}
|
||||
'exit' {
|
||||
g.code_gen.gen_exit(node.args[0].expr)
|
||||
} else if node.name in ['println', 'print', 'eprintln', 'eprint'] {
|
||||
}
|
||||
'println', 'print', 'eprintln', 'eprint' {
|
||||
expr := node.args[0].expr
|
||||
typ := node.args[0].typ
|
||||
g.gen_print_from_expr(expr, typ, node.name)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
g.code_gen.call_fn(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.FloatLiteral {
|
||||
val := g.eval.expr(node, ast.float_literal_type_idx).float_val()
|
||||
g.code_gen.load_fp(val)
|
||||
}
|
||||
ast.Ident {
|
||||
var := g.get_var_from_ident(node)
|
||||
// XXX this is intel specific
|
||||
match var {
|
||||
LocalVar {
|
||||
if g.is_register_type(var.typ) {
|
||||
g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), node as ast.Ident)
|
||||
} else if var.typ.is_pure_float() {
|
||||
g.code_gen.load_fp_var(node as ast.Ident)
|
||||
} else {
|
||||
ts := g.table.sym(g.unwrap(var.typ))
|
||||
match ts.info {
|
||||
ast.Struct {
|
||||
g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), g.get_var_offset(node.name))
|
||||
}
|
||||
ast.Enum {
|
||||
g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), node as ast.Ident,
|
||||
typ: ast.int_type_idx
|
||||
)
|
||||
}
|
||||
else {
|
||||
g.n_error('Unsupported variable type')
|
||||
}
|
||||
}
|
||||
}
|
||||
g.local_var_ident(node, var)
|
||||
}
|
||||
else {
|
||||
g.n_error('Unsupported variable kind')
|
||||
@ -131,12 +113,38 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
ast.ConcatExpr {
|
||||
g.code_gen.gen_concat_expr(node)
|
||||
}
|
||||
ast.TypeOf {
|
||||
g.gen_typeof_expr(node, false)
|
||||
}
|
||||
else {
|
||||
g.n_error('expr: unhandled node type: ${node.type_name()}')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) local_var_ident(ident ast.Ident, var LocalVar) {
|
||||
if g.is_register_type(var.typ) {
|
||||
g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), ident)
|
||||
} else if g.is_fp_type(var.typ) {
|
||||
g.code_gen.load_fp_var(ident)
|
||||
} else {
|
||||
ts := g.table.sym(g.unwrap(var.typ))
|
||||
match ts.info {
|
||||
ast.Struct {
|
||||
g.code_gen.lea_var_to_reg(g.code_gen.main_reg(), g.get_var_offset(ident.name))
|
||||
}
|
||||
ast.Enum {
|
||||
g.code_gen.mov_var_to_reg(g.code_gen.main_reg(), ident,
|
||||
typ: ast.int_type_idx
|
||||
)
|
||||
}
|
||||
else {
|
||||
g.n_error('Unsupported variable type')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) condition(expr ast.Expr, neg bool) int {
|
||||
g.expr(expr)
|
||||
g.code_gen.cmp_zero(g.code_gen.main_reg())
|
||||
@ -213,10 +221,66 @@ fn (mut g Gen) postfix_expr(node ast.PostfixExpr) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_typeof_expr(it ast.TypeOf, newline bool) {
|
||||
fn (mut g Gen) fn_decl_str(info ast.FnType) string {
|
||||
mut fn_str := 'fn ('
|
||||
for i, arg in info.func.params {
|
||||
if arg.is_mut {
|
||||
fn_str += 'mut '
|
||||
}
|
||||
if i > 0 {
|
||||
fn_str += ', '
|
||||
}
|
||||
fn_str += util.strip_main_name(g.table.get_type_name(arg.typ))
|
||||
}
|
||||
fn_str += ')'
|
||||
if info.func.return_type == ast.ovoid_type {
|
||||
fn_str += ' ?'
|
||||
} else if info.func.return_type == ast.rvoid_type {
|
||||
fn_str += ' !'
|
||||
} else if info.func.return_type != ast.void_type {
|
||||
x := util.strip_main_name(g.table.get_type_name(info.func.return_type))
|
||||
if info.func.return_type.has_flag(.option) {
|
||||
fn_str += ' ?${x}'
|
||||
} else if info.func.return_type.has_flag(.result) {
|
||||
fn_str += ' !${x}'
|
||||
} else {
|
||||
fn_str += ' ${x}'
|
||||
}
|
||||
}
|
||||
return fn_str
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_typeof_expr(node ast.TypeOf, newline bool) {
|
||||
nl := if newline { '\n' } else { '' }
|
||||
r := g.typ(it.typ).name
|
||||
g.code_gen.learel(g.code_gen.main_reg(), g.allocate_string('${r}${nl}', 3, .rel32))
|
||||
ts := g.table.sym(node.typ)
|
||||
mut str := ''
|
||||
|
||||
match ts.kind {
|
||||
.sum_type {
|
||||
g.n_error('`typeof()` is not implemented for sum types yet')
|
||||
}
|
||||
.array_fixed {
|
||||
fixed_info := ts.info as ast.ArrayFixed
|
||||
typ_name := g.table.get_type_name(fixed_info.elem_type)
|
||||
str = '[${fixed_info.size}]${util.strip_main_name(typ_name)}'
|
||||
}
|
||||
.function {
|
||||
func_info := ts.info as ast.FnType
|
||||
if node.typ.is_ptr() {
|
||||
str = '&'
|
||||
}
|
||||
str += g.fn_decl_str(func_info)
|
||||
}
|
||||
else {
|
||||
str = util.strip_main_name(if node.typ.has_flag(.variadic) {
|
||||
g.table.sym(g.table.value_type(node.typ)).name
|
||||
} else {
|
||||
g.table.type_to_str(node.typ)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
g.code_gen.learel(g.code_gen.main_reg(), g.allocate_string('${str}${nl}', 3, .rel32))
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_print_from_expr(expr ast.Expr, typ ast.Type, name string) {
|
||||
|
@ -41,6 +41,7 @@ mut:
|
||||
var_offset map[string]int // local var stack offset
|
||||
var_alloc_size map[string]int // local var allocation size
|
||||
stack_var_pos int
|
||||
stack_depth int
|
||||
debug_pos int
|
||||
errors []errors.Error
|
||||
warnings []errors.Warning
|
||||
@ -230,6 +231,11 @@ union F64I64 {
|
||||
i i64
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn byt(n int, s int) u8 {
|
||||
return u8((n >> (s * 8)) & 0xff)
|
||||
}
|
||||
|
||||
fn (mut g Gen) get_var_from_ident(ident ast.Ident) IdentVar {
|
||||
mut obj := ident.obj
|
||||
if obj !in [ast.Var, ast.ConstField, ast.GlobalField, ast.AsmRegister] {
|
||||
@ -735,9 +741,15 @@ fn (mut g Gen) get_multi_return(types []ast.Type) MultiReturn {
|
||||
return ret
|
||||
}
|
||||
|
||||
fn (g Gen) is_register_type(typ ast.Type) bool {
|
||||
return typ.is_pure_int() || typ == ast.char_type_idx || typ.is_any_kind_of_pointer()
|
||||
|| typ.is_bool()
|
||||
fn (mut g Gen) is_register_type(typ ast.Type) bool {
|
||||
return typ.is_pure_int() || typ == ast.char_type_idx
|
||||
|| typ.is_any_kind_of_pointer() || typ.is_bool()
|
||||
|| (g.table.sym(typ).info is ast.Alias && g.is_register_type(g.unwrap(typ)))
|
||||
}
|
||||
|
||||
fn (mut g Gen) is_fp_type(typ ast.Type) bool {
|
||||
return typ.is_pure_float()
|
||||
|| (g.table.sym(typ).info is ast.Alias && g.is_fp_type(g.unwrap(typ)))
|
||||
}
|
||||
|
||||
fn (mut g Gen) get_sizeof_ident(ident ast.Ident) int {
|
||||
@ -981,12 +993,17 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
||||
}
|
||||
|
||||
g.stack_var_pos = 0
|
||||
g.stack_depth = 0
|
||||
g.register_function_address(name)
|
||||
g.labels = &LabelTable{}
|
||||
g.defer_stmts.clear()
|
||||
g.return_type = node.return_type
|
||||
g.code_gen.fn_decl(node)
|
||||
g.patch_labels()
|
||||
|
||||
if g.stack_depth != 0 {
|
||||
g.println('^^^ stack_depth != 0 (${g.stack_depth}) !!!')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) register_function_address(name string) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
fn main() {
|
||||
test_int()
|
||||
test_fp()
|
||||
test_unsafe()
|
||||
test_alias(100, 9)
|
||||
}
|
||||
|
||||
fn test_int() {
|
||||
@ -26,3 +28,20 @@ fn test_fp() {
|
||||
|
||||
println(int(b))
|
||||
}
|
||||
|
||||
fn test_unsafe() {
|
||||
a := 10
|
||||
|
||||
unsafe {
|
||||
b := 4
|
||||
println(a + b)
|
||||
}
|
||||
}
|
||||
|
||||
type Integer = int
|
||||
|
||||
fn test_alias(a Integer, b Integer) {
|
||||
e := a + b
|
||||
assert e == a + b
|
||||
println(e)
|
||||
}
|
@ -1,2 +1,4 @@
|
||||
246
|
||||
3
|
||||
14
|
||||
109
|
||||
|
@ -56,6 +56,9 @@ fn struct_test() {
|
||||
mut f := &e
|
||||
f.a = 3
|
||||
assert e.a == 3
|
||||
|
||||
g := &Mutable{2}
|
||||
assert g.a == 2
|
||||
}
|
||||
|
||||
type AliasedStruct = Mutable
|
||||
|
@ -1,16 +1,86 @@
|
||||
type IntegerAlias = int
|
||||
|
||||
struct Test {
|
||||
a int = 0
|
||||
b voidptr = voidptr(0)
|
||||
c &Test = unsafe { 0 }
|
||||
d map[int][3]string = {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// strings
|
||||
a := 'string'
|
||||
t := typeof(a)
|
||||
println(t)
|
||||
t2 := typeof('another string')
|
||||
println(t2)
|
||||
|
||||
// integers
|
||||
n := 123
|
||||
t3 := typeof(n)
|
||||
println(t3)
|
||||
t4 := typeof(123)
|
||||
println(t4)
|
||||
// id := 'hello world'
|
||||
// println(id)
|
||||
test_alias(0)
|
||||
|
||||
// pointers
|
||||
t5 := typeof(voidptr(0))
|
||||
println(t5)
|
||||
t6 := typeof(charptr(0))
|
||||
println(t6)
|
||||
t7 := typeof(&u8(3))
|
||||
println(t7)
|
||||
|
||||
// functions
|
||||
t8 := typeof(main)
|
||||
println(t8)
|
||||
t9 := typeof(test_alias)
|
||||
println(t9)
|
||||
t10 := typeof(return_func)
|
||||
println(t10)
|
||||
|
||||
// arrays
|
||||
t11 := typeof([]int{})
|
||||
println(t11)
|
||||
t12 := typeof([16]int{})
|
||||
println(t12)
|
||||
|
||||
// maps
|
||||
t13 := typeof(map[int]string)
|
||||
println(t13)
|
||||
t14 := typeof(map[int][2]int)
|
||||
println(t14)
|
||||
|
||||
// options, results
|
||||
t15 := typeof(result_func)
|
||||
println(t15)
|
||||
t16 := typeof(result_func())
|
||||
println(t16)
|
||||
t17 := typeof(opt_func)
|
||||
println(t17)
|
||||
t18 := typeof(opt_func())
|
||||
println(t18)
|
||||
|
||||
// structs
|
||||
t19 := typeof(Test{})
|
||||
println(t19)
|
||||
t20 := typeof(Test{}.d)
|
||||
println(t20)
|
||||
}
|
||||
|
||||
fn test_alias(t IntegerAlias) {
|
||||
t1 := typeof(t)
|
||||
println(t1)
|
||||
}
|
||||
|
||||
fn return_func(foo int, bar []int, baz voidptr) string {
|
||||
return ''
|
||||
}
|
||||
|
||||
fn result_func() !int {
|
||||
return 0
|
||||
}
|
||||
|
||||
fn opt_func() ?int {
|
||||
return 0
|
||||
}
|
@ -2,3 +2,20 @@ string
|
||||
string
|
||||
int
|
||||
int literal
|
||||
IntegerAlias
|
||||
voidptr
|
||||
charptr
|
||||
&u8
|
||||
fn ()
|
||||
fn (IntegerAlias)
|
||||
fn (int, []int, voidptr) string
|
||||
[]int
|
||||
[16]int
|
||||
map[int]string
|
||||
map[int][2]int
|
||||
fn () !int
|
||||
!int
|
||||
fn () ?int
|
||||
?int
|
||||
Test
|
||||
map[int][3]string
|
||||
|
Loading…
Reference in New Issue
Block a user