cgen: optionals
parent
9bcb7d115f
commit
b173cea177
|
@ -244,9 +244,10 @@ pub mut:
|
|||
|
||||
pub struct IdentVar {
|
||||
pub mut:
|
||||
typ table.Type
|
||||
is_mut bool
|
||||
is_static bool
|
||||
typ table.Type
|
||||
is_mut bool
|
||||
is_static bool
|
||||
is_optional bool
|
||||
}
|
||||
|
||||
pub type IdentInfo = IdentFn | IdentVar
|
||||
|
|
|
@ -733,6 +733,7 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
|||
ident.kind = .variable
|
||||
ident.info = ast.IdentVar{
|
||||
typ: typ
|
||||
is_optional: table.type_is_optional(typ)
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ pub fn (g mut Gen) init() {
|
|||
}
|
||||
|
||||
// V type to C type
|
||||
pub fn (g &Gen) typ(t table.Type) string {
|
||||
pub fn (g mut Gen) typ(t table.Type) string {
|
||||
nr_muls := table.type_nr_muls(t)
|
||||
sym := g.table.get_type_symbol(t)
|
||||
mut styp := sym.name.replace_each(['.', '__'])
|
||||
|
@ -65,6 +65,10 @@ pub fn (g &Gen) typ(t table.Type) string {
|
|||
// TODO perf and other C structs
|
||||
styp = 'struct stat'
|
||||
}
|
||||
if table.type_is_optional(t) {
|
||||
styp = 'Option_' + styp
|
||||
g.definitions.writeln('typedef Option $styp;')
|
||||
}
|
||||
return styp
|
||||
}
|
||||
|
||||
|
@ -264,26 +268,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
}
|
||||
ast.Import {}
|
||||
ast.Return {
|
||||
g.write('return')
|
||||
// multiple returns
|
||||
if it.exprs.len > 1 {
|
||||
styp := g.typ(g.fn_decl.return_type)
|
||||
g.write(' ($styp){')
|
||||
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 if it.exprs.len == 1 {
|
||||
g.write(' ')
|
||||
g.expr(it.exprs[0])
|
||||
}
|
||||
g.writeln(';')
|
||||
g.return_statement(it)
|
||||
}
|
||||
ast.StructDecl {
|
||||
name := it.name.replace('.', '__')
|
||||
|
@ -621,13 +606,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||
g.write(it.val)
|
||||
}
|
||||
ast.Ident {
|
||||
name := it.name.replace('.', '__')
|
||||
if name.starts_with('C__') {
|
||||
g.write(name[3..])
|
||||
}
|
||||
else {
|
||||
g.write(name)
|
||||
}
|
||||
g.ident(it)
|
||||
}
|
||||
ast.IfExpr {
|
||||
// If expression? Assign the value to a temp var.
|
||||
|
@ -798,7 +777,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||
g.write(')')
|
||||
}
|
||||
ast.None {
|
||||
g.write('0')
|
||||
g.write('opt_none()')
|
||||
}
|
||||
ast.ParExpr {
|
||||
g.write('(')
|
||||
|
@ -965,6 +944,27 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (g mut Gen) ident(node ast.Ident) {
|
||||
name := node.name.replace('.', '__')
|
||||
if name.starts_with('C__') {
|
||||
g.write(name[3..])
|
||||
}
|
||||
else {
|
||||
// TODO `is`
|
||||
match node.info {
|
||||
ast.IdentVar {
|
||||
if it.is_optional {
|
||||
styp := g.typ(it.typ)[7..] // Option_int => int TODO perf?
|
||||
g.write('(*($styp*)${name}.data)')
|
||||
return
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
g.write(name)
|
||||
}
|
||||
}
|
||||
|
||||
fn (g mut Gen) index_expr(node ast.IndexExpr) {
|
||||
// TODO else doesn't work with sum types
|
||||
mut is_range := false
|
||||
|
@ -1041,6 +1041,51 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (g mut Gen) return_statement(it ast.Return) {
|
||||
g.write('return')
|
||||
// multiple returns
|
||||
if it.exprs.len > 1 {
|
||||
styp := g.typ(g.fn_decl.return_type)
|
||||
g.write(' ($styp){')
|
||||
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 if it.exprs.len == 1 {
|
||||
g.write(' ')
|
||||
// `return opt_ok(expr)` for functions that expect an optional
|
||||
if table.type_is_optional(g.fn_decl.return_type) {
|
||||
mut is_none := false
|
||||
mut is_error := false
|
||||
match it.exprs[0] {
|
||||
ast.None {
|
||||
is_none = true
|
||||
}
|
||||
ast.CallExpr {
|
||||
is_error = true // TODO check name 'error'
|
||||
}
|
||||
else {}
|
||||
}
|
||||
if !is_none && !is_error {
|
||||
g.write('opt_ok(')
|
||||
g.expr(it.exprs[0])
|
||||
styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_'
|
||||
g.writeln(', sizeof($styp));')
|
||||
return
|
||||
}
|
||||
// g.write('/*OPTIONAL*/')
|
||||
}
|
||||
g.expr(it.exprs[0])
|
||||
}
|
||||
g.writeln(';')
|
||||
}
|
||||
|
||||
fn (g mut Gen) const_decl(node ast.ConstDecl) {
|
||||
for i, field in node.fields {
|
||||
name := field.name.replace('.', '__')
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module table
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
module table
|
||||
|
||||
import os
|
||||
|
||||
// Once we have a module format we can read from module file instead
|
||||
// this is not optimal
|
||||
pub fn (table &Table) qualify_module(mod string, file_path string) string {
|
||||
for m in table.imports {
|
||||
if m.contains('.') && m.contains(mod) {
|
||||
m_parts := m.split('.')
|
||||
m_path := m_parts.join(os.path_separator)
|
||||
if mod == m_parts[m_parts.len - 1] && file_path.contains(m_path) {
|
||||
return m
|
||||
}
|
||||
}
|
||||
}
|
||||
return mod
|
||||
}
|
|
@ -5,6 +5,7 @@ module table
|
|||
|
||||
import (
|
||||
strings
|
||||
os
|
||||
)
|
||||
|
||||
pub struct Table {
|
||||
|
@ -60,7 +61,7 @@ pub fn (t mut Table) register_global(name string, typ Type) {
|
|||
// mod: p.mod
|
||||
// is_mut: true
|
||||
// idx: -1
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,3 +495,18 @@ pub fn (t &Table) check(got, expected Type) bool {
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Once we have a module format we can read from module file instead
|
||||
// this is not optimal
|
||||
pub fn (table &Table) qualify_module(mod string, file_path string) string {
|
||||
for m in table.imports {
|
||||
if m.contains('.') && m.contains(mod) {
|
||||
m_parts := m.split('.')
|
||||
m_path := m_parts.join(os.path_separator)
|
||||
if mod == m_parts[m_parts.len - 1] && file_path.contains(m_path) {
|
||||
return m
|
||||
}
|
||||
}
|
||||
}
|
||||
return mod
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue