1
0
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:
joe-conigliaro 2020-01-07 22:10:07 +11:00 committed by Alexander Medvednikov
parent 8c5923297e
commit b7509577b5
10 changed files with 121 additions and 57 deletions

View File

@ -121,7 +121,7 @@ pub:
pub struct Return {
pub:
expr Expr
exprs []Expr
}
/*

View File

@ -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 {

View File

@ -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 {

View File

@ -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) {
}

View File

@ -51,5 +51,10 @@ fn myuser() {
b2 := user.age > 0
}
fn multi_return() (int,string) {
return 4, 'four'
}
fn variadic(a ...int) {
}

View File

@ -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)
}
}
}
}
}
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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)
)