vh fixes for the UI module
parent
5be8b47e1c
commit
128d37c671
|
@ -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
|
||||
|
@ -379,23 +379,23 @@ fn array_eq<T>(a1, a2 []T) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
pub fn (a []int) eq(a2 []int) bool {
|
||||
return array_eq(a, a2)
|
||||
pub fn (a []int) eq(a2 []int) bool {
|
||||
return array_eq(a, a2)
|
||||
}
|
||||
|
||||
pub fn (a []i64) eq(a2 []i64) bool {
|
||||
return array_eq(a, a2)
|
||||
pub fn (a []i64) eq(a2 []i64) bool {
|
||||
return array_eq(a, a2)
|
||||
}
|
||||
|
||||
pub fn (a []string) eq(a2 []string) bool {
|
||||
return array_eq(a, a2)
|
||||
pub fn (a []string) eq(a2 []string) bool {
|
||||
return array_eq(a, a2)
|
||||
}
|
||||
|
||||
pub fn (a []byte) eq(a2 []byte) bool {
|
||||
return array_eq(a, a2)
|
||||
pub fn (a []byte) eq(a2 []byte) bool {
|
||||
return array_eq(a, a2)
|
||||
}
|
||||
|
||||
pub fn (a []f32) eq(a2 []f32) bool {
|
||||
return array_eq(a, a2)
|
||||
pub fn (a []f32) eq(a2 []f32) bool {
|
||||
return array_eq(a, a2)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
// ==
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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'
|
||||
|
@ -64,9 +62,10 @@ fn generate_vh(mod string) {
|
|||
continue
|
||||
}
|
||||
match tok.tok {
|
||||
.key_fn { fns.writeln(generate_fn(p.tokens, i)) }
|
||||
.key_const { consts.writeln(generate_const(p.tokens, i)) }
|
||||
.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'))
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
|
@ -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('')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
'
|
||||
)
|
||||
|
|
|
@ -4,6 +4,7 @@ module darwin
|
|||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#flag -framework Cocoa
|
||||
#flag -framework Carbon
|
||||
|
||||
struct C.NSString { }
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
module main
|
||||
|
||||
import (
|
||||
ui
|
||||
gx
|
||||
|
|
Loading…
Reference in New Issue