vh fixes for the UI module

pull/2606/head
Alexander Medvednikov 2019-10-31 13:08:01 +03:00
parent 5be8b47e1c
commit 128d37c671
11 changed files with 72 additions and 176 deletions

View File

@ -17,7 +17,7 @@ pub:
}
// Private function, used by V (`nums := []int`)
fn new_array(mylen, cap, elm_size int) array {
pub fn new_array(mylen, cap, elm_size int) array {
arr := array {
len: mylen
cap: cap

View File

@ -186,7 +186,7 @@ pub fn free(ptr voidptr) {
C.free(ptr)
}
fn memdup(src voidptr, sz int) voidptr {
pub fn memdup(src voidptr, sz int) voidptr {
mem := malloc(sz)
return C.memcpy(mem, src, sz)
}

View File

@ -41,7 +41,7 @@ NB: A V string should be/is immutable from the point of view of
when used with modules using C functions (for example os and so on).
*/
import strconv
//import strconv
pub struct string {
//mut:
@ -84,7 +84,7 @@ pub fn tos_clone(s byteptr) string {
// Same as `tos`, but calculates the length. Called by `string(bytes)` casts.
// Used only internally.
fn tos2(s byteptr) string {
pub fn tos2(s byteptr) string {
if s == 0 {
panic('tos2: nil string')
}
@ -94,7 +94,7 @@ fn tos2(s byteptr) string {
}
}
fn tos3(s *C.char) string {
pub fn tos3(s *C.char) string {
if s == 0 {
panic('tos3: nil string')
}
@ -202,7 +202,8 @@ pub fn (s string) int() int {
pub fn (s string) i64() i64 {
return strconv.parse_int(s, 0, 64)
//return strconv.parse_int(s, 0, 64)
return C.atoll(*char(s.str))
}
pub fn (s string) f32() f32 {
@ -214,11 +215,13 @@ pub fn (s string) f64() f64 {
}
pub fn (s string) u32() u32 {
return strconv.parse_uint(s, 0, 32)
return C.atol(*char(s.str))
//return strconv.parse_uint(s, 0, 32)
}
pub fn (s string) u64() u64 {
return strconv.parse_uint(s, 0, 64)
return C.atoll(*char(s.str))
//return strconv.parse_uint(s, 0, 64)
}
// ==

View File

@ -44,6 +44,7 @@ mut:
body_idx int // idx of the first body statement
fn_name_token_idx int // used by error reporting
comptime_define string
is_used bool // so that we can skip unused fns in resulting C code
}
struct TypeInst {
@ -193,9 +194,10 @@ fn (p mut Parser) fn_decl() {
else {
}
*/
is_pub := p.tok == .key_pub
mut f := Fn{
mod: p.mod
is_public: p.tok == .key_pub || p.is_vh // functions defined in .vh are always public
is_public: is_pub || p.is_vh // functions defined in .vh are always public
is_unsafe: p.attr == 'unsafe_fn'
is_deprecated: p.attr == 'deprecated'
comptime_define: if p.attr.starts_with('if ') { p.attr.right(3) } else { '' }
@ -204,12 +206,13 @@ fn (p mut Parser) fn_decl() {
if p.attr == 'live' && p.first_pass() && !p.pref.is_live && !p.pref.is_so {
println('INFO: run `v -live program.v` if you want to use [live] functions')
}
if f.is_public {
if is_pub {
p.next()
}
p.returns = false
//p.gen('/* returns $p.returns */')
p.next()
// Method receiver
mut receiver_typ := ''
if p.tok == .lpar {
@ -277,9 +280,9 @@ fn (p mut Parser) fn_decl() {
// C function header def? (fn C.NSMakeRect(int,int,int,int))
is_c := f.name == 'C' && p.tok == .dot
// Just fn signature? only builtin.v + default build mode
//if p.pref.is_verbose {
if p.is_vh {
//println('\n\nfn_decl() name=$f.name receiver_typ=$receiver_typ nogen=$p.cgen.nogen')
//}
}
if is_c {
p.check(.dot)
f.name = p.check_name()
@ -691,6 +694,7 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
p.error('use `malloc()` instead of `C.malloc()`')
}
}
f.is_used = true
cgen_name := p.table.fn_gen_name(f)
p.next() // fn name
if p.tok == .lt {

View File

@ -20,8 +20,6 @@ fn generate_vh(mod string) {
println('\n\n\n\nGenerating a V header file for module `$mod`')
vexe := os.executable()
full_mod_path := os.dir(vexe) + '/' + mod
mod_path := mod.replace('.', os.path_separator)
dir := if mod.starts_with('vlib') {
'$compiler.v_modules_path${os.path_separator}$mod'
@ -67,6 +65,7 @@ fn generate_vh(mod string) {
.key_fn { fns.writeln(generate_fn(p.tokens, i)) }
.key_const { consts.writeln(generate_const(p.tokens, i)) }
.key_struct { types.writeln(generate_type(p.tokens, i)) }
.key_type { types.writeln(generate_alias(p.tokens, i)) }
}
}
}
@ -105,6 +104,22 @@ fn generate_fn(tokens []Token, i int) string {
return out.str()
}
fn generate_alias(tokens []Token, i int) string {
mut out := strings.new_builder(100)
mut tok := tokens[i]
for i < tokens.len-1 {
out.write(tok.str())
out.write(' ')
if tok.line_nr != tokens[i+1].line_nr {
break
}
i++
tok = tokens[i]
}
out.writeln('\n')
return out.str()
}
fn generate_const(tokens []Token, i int) string {
mut out := strings.new_builder(100)
mut tok := tokens[i]
@ -137,148 +152,4 @@ fn generate_type(tokens []Token, i int) string {
return out.str()
}
/*
fn (v &V) generate_vh_old() {
println('\n\n\n\nGenerating a V header file for module `$v.mod`')
mod_path := v.mod.replace('.', os.path_separator)
dir := if v.dir.starts_with('vlib') {
'$v_modules_path${os.path_separator}$v.dir'
} else {
'$v_modules_path${os.path_separator}$mod_path'
}
path := dir + '.vh'
pdir := dir.all_before_last(os.path_separator)
if !os.dir_exists(pdir) {
os.mkdir_all(pdir)
// os.mkdir(os.realpath(dir))
}
file := os.create(path) or { panic(err) }
// Consts
mod_def := if v.mod.contains('.') { v.mod.all_after('.') } else { v.mod }
file.writeln('// $v.mod module header \n')
file.writeln('module $mod_def')
file.writeln('// Consts')
if v.table.consts.len > 0 {
file.writeln('const (')
for i, c in v.table.consts {
if c.mod != v.mod {
continue
}
// println('$i $c.name')
//if !c.name.contains('__') {
//continue
//}
name := c.name.all_after('__')
typ := v_type_str(c.typ)
file.writeln('\t$name $typ')
}
file.writeln(')\n')
// Globals
for var in v.table.consts {
if var.mod != v.mod {
continue
}
if !var.is_global {
continue
}
name := var.name.all_after('__')
typ := v_type_str(var.typ)
file.writeln('__global $name $typ')
}
file.writeln('\n')
}
// Types
file.writeln('// Types')
for _, typ in v.table.typesmap {
//println(typ.name)
if typ.mod != v.mod && typ.mod != ''{ // int, string etc mod == ''
// println('skipping type "$typ.name"')
continue
}
if typ.name.contains('_V_MulRet') {
continue
}
mut name := typ.name
if typ.name.contains('__') {
name = typ.name.all_after('__')
}
// type alias
if typ.parent != '' && typ.cat == .alias {
parent := v_type_str(typ.parent)
file.writeln('type $typ.name $parent')
}
if typ.cat in [TypeCategory.struct_, .c_struct] {
c := if typ.is_c { 'C.' } else { '' }
file.writeln('struct ${c}$name {')
// Private fields
for field in typ.fields {
if field.access_mod == .public {
continue
}
field_type := v_type_str(field.typ).replace('*', '&')
file.writeln('\t$field.name $field_type')
}
//file.writeln('pub:')
mut public_str := ''
for field in typ.fields {
if field.access_mod == .private {
continue
}
field_type := v_type_str(field.typ).replace('*', '&')
public_str += '\t$field.name $field_type\n'
//file.writeln('\t$field.name $field_type')
}
if public_str != '' {
file.writeln('pub:' + public_str)
}
file.writeln('}\n')
}
}
// Functions & methods
file.writeln('// Functions')
// Public first
mut fns := []Fn
// TODO fns := v.table.fns.filter(.mod == v.mod)
for _, f in v.table.fns {
if f.mod == v.mod || f.mod == ''{
fns << f
} else {
//println('skipping fn $f.name mod=$f.mod')
}
}
for _, f in fns {
if !f.is_public {
continue
}
file.writeln(f.v_definition())
}
// Private
for _, f in fns {
if f.is_public {
continue
}
file.writeln(f.v_definition())
}
// Methods
file.writeln('\n// Methods //////////////////')
for _, typ in v.table.typesmap {
if typ.mod != v.mod && !(v.mod == 'builtin' && typ.mod == '') {
// println('skipping method typ $typ.name mod=$typ.mod')
continue
}
for method in typ.methods {
file.writeln(method.v_definition())
}
}
file.close()
/*
for i, p in v.parsers {
if v.parsers[i].vh_lines.len > 0 {
os.write_file(p.file_name +'.vh', v.parsers[i].vh_lines.join('\n'))
}
}
*/
}
*/

View File

@ -508,6 +508,7 @@ fn (p mut Parser) import_statement() {
}
fn (p mut Parser) const_decl() {
//println('const decl $p.file_path')
is_pub := p.tok == .key_pub
if is_pub {
p.next()
@ -534,10 +535,16 @@ fn (p mut Parser) const_decl() {
name = p.prepend_mod(name)
mut typ := ''
if p.is_vh {
// .vh files don't have const values, just types: `const (a int)`
//println('CONST VH $p.file_path')
// .vh files may not have const values, just types: `const (a int)`
if p.tok == .assign {
p.next()
// Otherwise parse the expression to get its type,
// but don't generate it. Const's value is generated
// in "module.o".
p.cgen.nogen = true
typ = p.expression()
p.cgen.nogen = false
} else {
typ = p.get_type()
}
@ -566,6 +573,13 @@ fn (p mut Parser) const_decl() {
}
}
}
if p.pass == .main && p.cgen.nogen && p.pref.build_mode == .build_module {
// We are building module `ui`, but are parsing `gx` right now
// (because of nogen). We need to import gx constants with `extern`.
//println('extern const mod=$p.mod name=$name')
p.cgen.consts << ('extern ' +
p.table.cgen_name_type_pair(name, typ)) + ';'
}
if p.pass == .main && !p.cgen.nogen {
// TODO hack
// cur_line has const's value right now. if it's just a number, then optimize generation:
@ -584,6 +598,7 @@ fn (p mut Parser) const_decl() {
}
else {
p.cgen.consts << p.table.cgen_name_type_pair(name, typ) + ';'
//println('adding to init "$name"')
p.cgen.consts_init << '$name = $p.cgen.cur_line;'
}
p.cgen.resetln('')

View File

@ -81,7 +81,7 @@ fn (p mut Parser) struct_decl() {
typ.is_placeholder = false
typ.cat = cat
typ.parent = objc_parent
typ.is_public = is_pub
typ.is_public = is_pub || p.is_vh
p.table.rewrite_type(typ)
}
else {
@ -91,7 +91,7 @@ fn (p mut Parser) struct_decl() {
is_c: is_c
cat: cat
parent: objc_parent
is_public: is_pub
is_public: is_pub || p.is_vh
}
}
// Struct `C.Foo` declaration, no body

View File

@ -65,12 +65,12 @@ Commands:
run <file.v> Build and execute the V program in file.v. You can add arguments for the V program *after* the file name.
build <module> Compile a module into an object file.
runrepl Run the V REPL. If V is running in a tty terminal, the REPL is interactive, otherwise it just reads from stdin.
symlink Useful on unix systems. Symlinks the current V executable to /usr/local/bin/v, so that V is globally available.
symlink Useful on Unix systems. Symlinks the current V executable to /usr/local/bin/v, so that V is globally available.
install <module> Install a user module from https://vpm.vlang.io/.
test v Run all V test files, and compile all V examples.
test folder/ Run all V test files located in the folder and its subfolders. You can also pass individual _test.v files too.
fmt Run vfmt to format the source code. [wip]
doc Run vdoc over the source code and produce documentation. [wip]
doc Run vdoc over the source code and produce documentation.
translate Translates C to V. [wip, will be available in V 0.3]
'
)

View File

@ -4,6 +4,7 @@ module darwin
#include <CoreFoundation/CoreFoundation.h>
#flag -framework Cocoa
#flag -framework Carbon
struct C.NSString { }

View File

@ -7,7 +7,7 @@ pub const (
path_separator = '/'
)
fn init_os_args(argc int, argv &byteptr) []string {
pub fn init_os_args(argc int, argv &byteptr) []string {
mut args := []string
for i in 0 .. argc {
args << string(argv[i])

View File

@ -1,3 +1,5 @@
module main
import (
ui
gx