mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v: cleanup & fixes. update variadic & multiple return
This commit is contained in:
parent
8c5923297e
commit
b7509577b5
@ -121,7 +121,7 @@ pub:
|
||||
|
||||
pub struct Return {
|
||||
pub:
|
||||
expr Expr
|
||||
exprs []Expr
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
strings
|
||||
v.ast
|
||||
v.table
|
||||
v.types
|
||||
term
|
||||
)
|
||||
|
||||
@ -11,6 +12,8 @@ struct Gen {
|
||||
out strings.Builder
|
||||
definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file)
|
||||
table &table.Table
|
||||
mut:
|
||||
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
||||
}
|
||||
|
||||
pub fn cgen(files []ast.File, table &table.Table) string {
|
||||
@ -19,6 +22,7 @@ pub fn cgen(files []ast.File, table &table.Table) string {
|
||||
out: strings.new_builder(100)
|
||||
definitions: strings.new_builder(100)
|
||||
table: table
|
||||
fn_decl: 0
|
||||
}
|
||||
for file in files {
|
||||
for stmt in file.stmts {
|
||||
@ -45,6 +49,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
match node {
|
||||
ast.Import {}
|
||||
ast.FnDecl {
|
||||
g.fn_decl = &it
|
||||
is_main := it.name == 'main'
|
||||
if is_main {
|
||||
g.write('int ${it.name}(')
|
||||
@ -53,8 +58,11 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
g.write('$it.ti.name ${it.name}(')
|
||||
g.definitions.write('$it.ti.name ${it.name}(')
|
||||
}
|
||||
for arg in it.args {
|
||||
for i, arg in it.args {
|
||||
g.write(arg.ti.name + ' ' + arg.name)
|
||||
if i < it.args.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
g.definitions.write(arg.ti.name + ' ' + arg.name)
|
||||
}
|
||||
g.writeln(') { ')
|
||||
@ -68,10 +76,26 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
g.writeln('return 0;')
|
||||
}
|
||||
g.writeln('}')
|
||||
g.fn_decl = 0
|
||||
}
|
||||
ast.Return {
|
||||
g.write('return ')
|
||||
g.expr(it.expr)
|
||||
// multiple returns
|
||||
if it.exprs.len > 1 {
|
||||
g.write('($g.fn_decl.ti.name){')
|
||||
for i, expr in it.exprs {
|
||||
g.write('.arg$i=')
|
||||
g.expr(expr)
|
||||
if i < it.exprs.len - 1 {
|
||||
g.write(',')
|
||||
}
|
||||
}
|
||||
g.write('}')
|
||||
}
|
||||
// normal return
|
||||
else {
|
||||
g.expr(it.exprs[0])
|
||||
}
|
||||
g.writeln(';')
|
||||
}
|
||||
ast.VarDecl {
|
||||
|
@ -46,7 +46,12 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||
}
|
||||
ast.Return {
|
||||
g.write('return ')
|
||||
g.expr(it.expr)
|
||||
if it.exprs.len > 0 {
|
||||
|
||||
}
|
||||
else {
|
||||
g.expr(it.exprs[0])
|
||||
}
|
||||
g.writeln(';')
|
||||
}
|
||||
ast.VarDecl {
|
||||
|
@ -2,6 +2,7 @@ void foo(int a);
|
||||
int get_int(string a);
|
||||
int get_int2();
|
||||
void myuser();
|
||||
multi_return_int_string multi_return();
|
||||
void variadic(variadic_int a);
|
||||
|
||||
typedef struct {
|
||||
@ -49,5 +50,9 @@ void myuser() {
|
||||
bool b2 = user.age > 0;
|
||||
}
|
||||
|
||||
multi_return_int_string multi_return() {
|
||||
return (multi_return_int_string){.arg0=4,.arg1=tos3("four")};
|
||||
}
|
||||
|
||||
void variadic(variadic_int a) {
|
||||
}
|
||||
|
@ -51,5 +51,10 @@ fn myuser() {
|
||||
b2 := user.age > 0
|
||||
}
|
||||
|
||||
fn multi_return() (int,string) {
|
||||
return 4, 'four'
|
||||
}
|
||||
|
||||
fn variadic(a ...int) {
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
module parser
|
||||
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
@ -40,10 +39,10 @@ pub fn (p mut Parser) parse_map_ti(nr_muls int) types.TypeIdent {
|
||||
|
||||
pub fn (p mut Parser) parse_multi_return_ti() types.TypeIdent {
|
||||
p.check(.lpar)
|
||||
mut mr_tis := []&types.TypeIdent
|
||||
mut mr_tis := []types.TypeIdent
|
||||
for {
|
||||
mr_ti := p.parse_ti()
|
||||
mr_tis << &mr_ti
|
||||
mr_tis << mr_ti
|
||||
if p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
}
|
||||
@ -99,52 +98,52 @@ pub fn (p mut Parser) parse_ti() types.TypeIdent {
|
||||
return p.parse_map_ti(nr_muls)
|
||||
}
|
||||
'voidptr' {
|
||||
return types.new_base_ti(._voidptr, nr_muls)
|
||||
return types.new_builtin_ti(._voidptr, nr_muls)
|
||||
}
|
||||
'byteptr' {
|
||||
return types.new_base_ti(._byteptr, nr_muls)
|
||||
return types.new_builtin_ti(._byteptr, nr_muls)
|
||||
}
|
||||
'charptr' {
|
||||
return types.new_base_ti(._charptr, nr_muls)
|
||||
return types.new_builtin_ti(._charptr, nr_muls)
|
||||
}
|
||||
'i8' {
|
||||
return types.new_base_ti(._i8, nr_muls)
|
||||
return types.new_builtin_ti(._i8, nr_muls)
|
||||
}
|
||||
'i16' {
|
||||
return types.new_base_ti(._i16, nr_muls)
|
||||
return types.new_builtin_ti(._i16, nr_muls)
|
||||
}
|
||||
'int' {
|
||||
return types.new_base_ti(._int, nr_muls)
|
||||
return types.new_builtin_ti(._int, nr_muls)
|
||||
}
|
||||
'i64' {
|
||||
return types.new_base_ti(._i64, nr_muls)
|
||||
return types.new_builtin_ti(._i64, nr_muls)
|
||||
}
|
||||
'byte' {
|
||||
return types.new_base_ti(._byte, nr_muls)
|
||||
return types.new_builtin_ti(._byte, nr_muls)
|
||||
}
|
||||
'u16' {
|
||||
return types.new_base_ti(._u16, nr_muls)
|
||||
return types.new_builtin_ti(._u16, nr_muls)
|
||||
}
|
||||
'u32' {
|
||||
return types.new_base_ti(._u32, nr_muls)
|
||||
return types.new_builtin_ti(._u32, nr_muls)
|
||||
}
|
||||
'u64' {
|
||||
return types.new_base_ti(._u64, nr_muls)
|
||||
return types.new_builtin_ti(._u64, nr_muls)
|
||||
}
|
||||
'f32' {
|
||||
return types.new_base_ti(._f32, nr_muls)
|
||||
return types.new_builtin_ti(._f32, nr_muls)
|
||||
}
|
||||
'f64' {
|
||||
return types.new_base_ti(._f64, nr_muls)
|
||||
return types.new_builtin_ti(._f64, nr_muls)
|
||||
}
|
||||
'string' {
|
||||
return types.new_base_ti(._string, nr_muls)
|
||||
return types.new_builtin_ti(._string, nr_muls)
|
||||
}
|
||||
'char' {
|
||||
return types.new_base_ti(._char, nr_muls)
|
||||
return types.new_builtin_ti(._char, nr_muls)
|
||||
}
|
||||
'bool' {
|
||||
return types.new_base_ti(._bool, nr_muls)
|
||||
return types.new_builtin_ti(._bool, nr_muls)
|
||||
}
|
||||
// struct / enum / placeholder
|
||||
else {
|
||||
@ -156,7 +155,7 @@ pub fn (p mut Parser) parse_ti() types.TypeIdent {
|
||||
}
|
||||
return types.new_ti(._placeholder, name, idx, nr_muls)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +120,9 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||
ti: ti
|
||||
name: arg_name
|
||||
}
|
||||
if ti.kind == ._variadic && p.tok.kind == .comma {
|
||||
p.error('cannot use ...(variadic) with non-final parameter $arg_name')
|
||||
}
|
||||
}
|
||||
if p.tok.kind != .rpar {
|
||||
p.check(.comma)
|
||||
@ -128,7 +131,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||
p.check(.rpar)
|
||||
// Return type
|
||||
mut ti := types.void_ti
|
||||
if p.tok.kind == .name {
|
||||
if p.tok.kind in [.name, .lpar] {
|
||||
ti = p.parse_ti()
|
||||
p.return_ti = ti
|
||||
}
|
||||
|
@ -630,19 +630,19 @@ fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
|
||||
fn (p mut Parser) parse_number_literal() (ast.Expr,types.TypeIdent) {
|
||||
lit := p.tok.lit
|
||||
mut node := ast.Expr{}
|
||||
mut ti := types.new_base_ti(._int, 0)
|
||||
mut ti := types.int_ti
|
||||
if lit.contains('.') {
|
||||
node = ast.FloatLiteral{
|
||||
// val: lit.f64()
|
||||
val: lit
|
||||
}
|
||||
ti = types.new_base_ti(._f64, 0)
|
||||
ti = types.new_builtin_ti(._f64, 0)
|
||||
}
|
||||
else {
|
||||
node = ast.IntegerLiteral{
|
||||
val: lit.int()
|
||||
}
|
||||
// ti = types.new_base_ti(._int, 0)
|
||||
// ti = types.int_ti
|
||||
}
|
||||
p.next()
|
||||
return node,ti
|
||||
@ -709,12 +709,37 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||
|
||||
fn (p mut Parser) return_stmt() ast.Return {
|
||||
p.next()
|
||||
expr,t := p.expr(0)
|
||||
if !types.check(p.return_ti, t) {
|
||||
p.warn('cannot use `$t.name` as type `$p.return_ti.name` in return argument')
|
||||
// return expressions
|
||||
mut exprs := []ast.Expr
|
||||
// return type idents
|
||||
mut got_tis := []types.TypeIdent
|
||||
for {
|
||||
expr,ti := p.expr(0)
|
||||
exprs << expr
|
||||
got_tis << ti
|
||||
if p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
}
|
||||
else {
|
||||
break
|
||||
}
|
||||
}
|
||||
mut expected_tis := [p.return_ti]
|
||||
if p.return_ti.kind == ._multi_return {
|
||||
mr_type := p.table.types[p.return_ti.idx] as types.MultiReturn
|
||||
expected_tis = mr_type.tis
|
||||
}
|
||||
if expected_tis.len != got_tis.len {
|
||||
p.error('wrong number of return arguments:\n\texpected: $expected_tis.str()\n\tgot: $got_tis.str()')
|
||||
}
|
||||
for i, exp_ti in expected_tis {
|
||||
got_ti := got_tis[i]
|
||||
if !types.check(exp_ti, got_ti) {
|
||||
p.error('cannot use `$got_ti.name` as type `$exp_ti.name` in return argument')
|
||||
}
|
||||
}
|
||||
return ast.Return{
|
||||
expr: expr
|
||||
exprs: exprs
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ pub fn (t &Table) find_type(name string) ?types.Type {
|
||||
}
|
||||
|
||||
pub fn (t mut Table) register_struct(typ types.Struct) int {
|
||||
mut struct_type := types.Type{}
|
||||
// existing
|
||||
existing_idx := t.type_idxs[typ.name]
|
||||
if existing_idx > 0 {
|
||||
@ -29,6 +28,7 @@ pub fn (t mut Table) register_struct(typ types.Struct) int {
|
||||
types.Placeholder {
|
||||
// override placeholder
|
||||
println('overriding type placeholder `$it.name` with struct')
|
||||
mut struct_type := types.Type{}
|
||||
struct_type = {
|
||||
typ |
|
||||
idx:existing_idx
|
||||
@ -42,12 +42,13 @@ pub fn (t mut Table) register_struct(typ types.Struct) int {
|
||||
else {
|
||||
panic('cannot register type `$typ.name`, another type with this name exists')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// register
|
||||
println('registering: $typ.name')
|
||||
idx := t.types.len
|
||||
t.type_idxs[typ.name] = idx
|
||||
mut struct_type := types.Type{}
|
||||
struct_type = {
|
||||
typ |
|
||||
idx:idx
|
||||
@ -121,14 +122,10 @@ pub fn (t mut Table) find_or_register_array_fixed(elem_ti &types.TypeIdent, size
|
||||
return idx,name
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_multi_return(mr_tis []&types.TypeIdent) (int,string) {
|
||||
pub fn (t mut Table) find_or_register_multi_return(mr_tis []types.TypeIdent) (int,string) {
|
||||
mut name := 'multi_return'
|
||||
mut mr_type_kinds := []types.Kind
|
||||
mut mr_type_idxs := []int
|
||||
for mr_ti in mr_tis {
|
||||
name += '_$mr_ti.name'
|
||||
mr_type_kinds << mr_ti.kind
|
||||
mr_type_idxs << mr_ti.idx
|
||||
}
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
@ -141,8 +138,7 @@ pub fn (t mut Table) find_or_register_multi_return(mr_tis []&types.TypeIdent) (i
|
||||
mr_type = types.MultiReturn{
|
||||
idx: idx
|
||||
name: name
|
||||
type_kinds: mr_type_kinds
|
||||
type_idxs: mr_type_idxs
|
||||
tis: mr_tis
|
||||
}
|
||||
t.type_idxs[name] = idx
|
||||
t.types << mr_type
|
||||
@ -161,8 +157,7 @@ pub fn (t mut Table) find_or_register_variadic(variadic_ti &types.TypeIdent) (in
|
||||
mut variadic_type := types.Type{}
|
||||
variadic_type = types.Variadic{
|
||||
idx: idx
|
||||
type_kind: variadic_ti.kind
|
||||
type_idx: variadic_ti.idx
|
||||
ti: variadic_ti
|
||||
}
|
||||
t.type_idxs[name] = idx
|
||||
t.types << variadic_type
|
||||
|
@ -54,8 +54,9 @@ pub fn new_ti(kind Kind, name string, idx int, nr_muls int) TypeIdent {
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn new_base_ti(kind Kind, nr_muls int) TypeIdent {
|
||||
pub fn new_builtin_ti(kind Kind, nr_muls int) TypeIdent {
|
||||
return TypeIdent{
|
||||
idx: -int(kind)
|
||||
kind: kind
|
||||
name: kind.str()
|
||||
nr_muls: nr_muls
|
||||
@ -83,7 +84,11 @@ pub fn (ti &TypeIdent) is_number() bool {
|
||||
}
|
||||
|
||||
pub fn (ti &TypeIdent) str() string {
|
||||
return '$ti.kind.str() $ti.idx: $ti.name ($ti.nr_muls)'
|
||||
mut muls := ''
|
||||
for _ in 0 .. ti.nr_muls {
|
||||
muls += '&'
|
||||
}
|
||||
return '$muls$ti.name'
|
||||
}
|
||||
|
||||
pub fn check(got, expected &TypeIdent) bool {
|
||||
@ -275,17 +280,15 @@ pub:
|
||||
|
||||
pub struct MultiReturn {
|
||||
pub:
|
||||
idx int
|
||||
name string
|
||||
type_kinds []Kind
|
||||
type_idxs []int
|
||||
idx int
|
||||
name string
|
||||
tis []TypeIdent
|
||||
}
|
||||
|
||||
pub struct Variadic {
|
||||
pub:
|
||||
idx int
|
||||
type_kind Kind
|
||||
type_idx int
|
||||
idx int
|
||||
ti TypeIdent
|
||||
}
|
||||
|
||||
pub fn (t Void) str() string {
|
||||
@ -353,7 +356,7 @@ pub fn (t MultiReturn) str() string {
|
||||
}
|
||||
|
||||
pub fn (t Variadic) str() string {
|
||||
return 'variadic_$t.type_kind.str()'
|
||||
return 'variadic_$t.ti.kind.str()'
|
||||
}
|
||||
|
||||
pub const (
|
||||
@ -387,8 +390,8 @@ pub const (
|
||||
)
|
||||
|
||||
pub const (
|
||||
void_ti = new_base_ti(._void, 0)
|
||||
int_ti = new_base_ti(._int, 0)
|
||||
string_ti = new_base_ti(._string, 0)
|
||||
bool_ti = new_base_ti(._bool, 0)
|
||||
void_ti = new_builtin_ti(._void, 0)
|
||||
int_ti = new_builtin_ti(._int, 0)
|
||||
string_ti = new_builtin_ti(._string, 0)
|
||||
bool_ti = new_builtin_ti(._bool, 0)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user