cgen: optionals
parent
9bcb7d115f
commit
b173cea177
|
@ -247,6 +247,7 @@ pub mut:
|
||||||
typ table.Type
|
typ table.Type
|
||||||
is_mut bool
|
is_mut bool
|
||||||
is_static bool
|
is_static bool
|
||||||
|
is_optional bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type IdentInfo = IdentFn | IdentVar
|
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.kind = .variable
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: typ
|
typ: typ
|
||||||
|
is_optional: table.type_is_optional(typ)
|
||||||
}
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub fn (g mut Gen) init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// V type to C type
|
// 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)
|
nr_muls := table.type_nr_muls(t)
|
||||||
sym := g.table.get_type_symbol(t)
|
sym := g.table.get_type_symbol(t)
|
||||||
mut styp := sym.name.replace_each(['.', '__'])
|
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
|
// TODO perf and other C structs
|
||||||
styp = 'struct stat'
|
styp = 'struct stat'
|
||||||
}
|
}
|
||||||
|
if table.type_is_optional(t) {
|
||||||
|
styp = 'Option_' + styp
|
||||||
|
g.definitions.writeln('typedef Option $styp;')
|
||||||
|
}
|
||||||
return styp
|
return styp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,26 +268,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
ast.Import {}
|
ast.Import {}
|
||||||
ast.Return {
|
ast.Return {
|
||||||
g.write('return')
|
g.return_statement(it)
|
||||||
// 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(';')
|
|
||||||
}
|
}
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
name := it.name.replace('.', '__')
|
name := it.name.replace('.', '__')
|
||||||
|
@ -621,13 +606,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write(it.val)
|
g.write(it.val)
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
name := it.name.replace('.', '__')
|
g.ident(it)
|
||||||
if name.starts_with('C__') {
|
|
||||||
g.write(name[3..])
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g.write(name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
// If expression? Assign the value to a temp var.
|
// If expression? Assign the value to a temp var.
|
||||||
|
@ -798,7 +777,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
ast.None {
|
ast.None {
|
||||||
g.write('0')
|
g.write('opt_none()')
|
||||||
}
|
}
|
||||||
ast.ParExpr {
|
ast.ParExpr {
|
||||||
g.write('(')
|
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) {
|
fn (g mut Gen) index_expr(node ast.IndexExpr) {
|
||||||
// TODO else doesn't work with sum types
|
// TODO else doesn't work with sum types
|
||||||
mut is_range := false
|
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) {
|
fn (g mut Gen) const_decl(node ast.ConstDecl) {
|
||||||
for i, field in node.fields {
|
for i, field in node.fields {
|
||||||
name := field.name.replace('.', '__')
|
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 (
|
import (
|
||||||
strings
|
strings
|
||||||
|
os
|
||||||
)
|
)
|
||||||
|
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
|
@ -494,3 +495,18 @@ pub fn (t &Table) check(got, expected Type) bool {
|
||||||
}
|
}
|
||||||
return true
|
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