ui: Objective-C @interface support for Cocoa; minor clean-ups
parent
fbc19311b5
commit
bf1ee28194
|
@ -63,16 +63,6 @@ fn (p &Parser) find_var_check_new_var(name string) ?Var {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (f &Fn) find_var2(name string) Var {
|
|
||||||
for i in 0 .. f.var_idx {
|
|
||||||
if f.local_vars[i].name == name {
|
|
||||||
return f.local_vars[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Var{}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn (p mut Parser) open_scope() {
|
fn (p mut Parser) open_scope() {
|
||||||
p.cur_fn.defer_text << ''
|
p.cur_fn.defer_text << ''
|
||||||
p.cur_fn.scope_level++
|
p.cur_fn.scope_level++
|
||||||
|
|
|
@ -71,26 +71,28 @@ fn (p mut Parser) gen_fn_decl(f Fn, typ, str_args string) {
|
||||||
fn types_to_c(types []Type, table &Table) string {
|
fn types_to_c(types []Type, table &Table) string {
|
||||||
mut sb := strings.new_builder(10)
|
mut sb := strings.new_builder(10)
|
||||||
for t in types {
|
for t in types {
|
||||||
if t.cat != .union_ && t.cat != .struct_ {
|
if t.cat != .union_ && t.cat != .struct_ && t.cat != .objc_interface {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
//if is_objc {
|
|
||||||
//sb.writeln('@interface $name : $objc_parent { @public')
|
|
||||||
//}
|
|
||||||
//if is_atomic {
|
//if is_atomic {
|
||||||
//sb.write('_Atomic ')
|
//sb.write('_Atomic ')
|
||||||
//}
|
//}
|
||||||
kind := if t.cat == .union_ {'union'} else {'struct'}
|
if t.cat == .objc_interface {
|
||||||
sb.writeln('$kind $t.name {')
|
sb.writeln('@interface $t.name : $t.parent { @public')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
kind := if t.cat == .union_ {'union'} else {'struct'}
|
||||||
|
sb.writeln('$kind $t.name {')
|
||||||
|
}
|
||||||
for field in t.fields {
|
for field in t.fields {
|
||||||
sb.write('\t')
|
sb.write('\t')
|
||||||
sb.writeln(table.cgen_name_type_pair(field.name,
|
sb.writeln(table.cgen_name_type_pair(field.name,
|
||||||
field.typ) + ';')
|
field.typ) + ';')
|
||||||
}
|
}
|
||||||
sb.writeln('};\n')
|
sb.writeln('};\n')
|
||||||
//if is_objc {
|
if t.cat == .objc_interface {
|
||||||
//sb.writeln('@end')
|
sb.writeln('@end')
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
return sb.str()
|
return sb.str()
|
||||||
}
|
}
|
||||||
|
|
|
@ -492,14 +492,17 @@ fn key_to_type_cat(tok Token) TypeCategory {
|
||||||
// also unions and interfaces
|
// also unions and interfaces
|
||||||
fn (p mut Parser) struct_decl() {
|
fn (p mut Parser) struct_decl() {
|
||||||
// V can generate Objective C for integration with Cocoa
|
// V can generate Objective C for integration with Cocoa
|
||||||
// `[interface:ParentInterface]`
|
// `[objc_interface:ParentInterface]`
|
||||||
//is_objc := p.attr.starts_with('interface')
|
is_objc := p.attr.starts_with('objc_interface')
|
||||||
//objc_parent := if is_objc { p.attr.right(10) } else { '' }
|
objc_parent := if is_objc { p.attr.right(15) } else { '' }
|
||||||
// interface, union, struct
|
// interface, union, struct
|
||||||
is_interface := p.tok == .key_interface
|
is_interface := p.tok == .key_interface
|
||||||
is_union := p.tok == .key_union
|
is_union := p.tok == .key_union
|
||||||
is_struct := p.tok == .key_struct
|
is_struct := p.tok == .key_struct
|
||||||
mut cat := key_to_type_cat(p.tok)
|
mut cat := key_to_type_cat(p.tok)
|
||||||
|
if is_objc {
|
||||||
|
cat = .objc_interface
|
||||||
|
}
|
||||||
p.fgen(p.tok.str() + ' ')
|
p.fgen(p.tok.str() + ' ')
|
||||||
// Get type name
|
// Get type name
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -530,7 +533,11 @@ fn (p mut Parser) struct_decl() {
|
||||||
if p.pass == .decl && p.table.known_type_fast(typ) {
|
if p.pass == .decl && p.table.known_type_fast(typ) {
|
||||||
p.error('`$name` redeclared')
|
p.error('`$name` redeclared')
|
||||||
}
|
}
|
||||||
if !is_c {
|
if is_objc {
|
||||||
|
// Forward declaration of an Objective-C interface with `@class` :)
|
||||||
|
p.gen_typedef('@class $name;')
|
||||||
|
}
|
||||||
|
else if !is_c {
|
||||||
kind := if is_union {'union'} else {'struct'}
|
kind := if is_union {'union'} else {'struct'}
|
||||||
p.gen_typedef('typedef $kind $name $name;')
|
p.gen_typedef('typedef $kind $name $name;')
|
||||||
}
|
}
|
||||||
|
@ -544,6 +551,7 @@ fn (p mut Parser) struct_decl() {
|
||||||
typ.is_c = is_c
|
typ.is_c = is_c
|
||||||
typ.is_placeholder = false
|
typ.is_placeholder = false
|
||||||
typ.cat = cat
|
typ.cat = cat
|
||||||
|
typ.parent = objc_parent
|
||||||
p.table.rewrite_type(typ)
|
p.table.rewrite_type(typ)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -552,6 +560,7 @@ fn (p mut Parser) struct_decl() {
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
is_c: is_c
|
is_c: is_c
|
||||||
cat: cat
|
cat: cat
|
||||||
|
parent: objc_parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Struct `C.Foo` declaration, no body
|
// Struct `C.Foo` declaration, no body
|
||||||
|
@ -1715,12 +1724,6 @@ fn (p mut Parser) name_expr() string {
|
||||||
p.error('undefined: `$name`')
|
p.error('undefined: `$name`')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if orig_name == 'i32' {
|
|
||||||
println('`i32` alias was removed, use `int` instead')
|
|
||||||
}
|
|
||||||
if orig_name == 'u8' {
|
|
||||||
println('`u8` alias was removed, use `byte` instead')
|
|
||||||
}
|
|
||||||
p.error('undefined: `$orig_name`')
|
p.error('undefined: `$orig_name`')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2852,42 +2855,11 @@ fn (p mut Parser) array_init() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) struct_init(typ string) string {
|
fn (p mut Parser) struct_init(typ string) string {
|
||||||
//p.gen('/* struct init */')
|
|
||||||
p.is_struct_init = true
|
p.is_struct_init = true
|
||||||
t := p.table.find_type(typ)
|
t := p.table.find_type(typ)
|
||||||
if p.gen_struct_init(typ, t) { return typ }
|
if p.gen_struct_init(typ, t) { return typ }
|
||||||
p.scanner.fmt_out.cut(typ.len)
|
p.scanner.fmt_out.cut(typ.len)
|
||||||
ptr := typ.contains('*')
|
ptr := typ.contains('*')
|
||||||
/*
|
|
||||||
if !ptr {
|
|
||||||
if p.is_c_struct_init {
|
|
||||||
// `face := C.FT_Face{}` => `FT_Face face;`
|
|
||||||
if p.tok == .rcbr {
|
|
||||||
p.is_empty_c_struct_init = true
|
|
||||||
p.check(.rcbr)
|
|
||||||
return typ
|
|
||||||
}
|
|
||||||
p.gen('(struct $typ) {')
|
|
||||||
p.is_c_struct_init = false
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.gen('($typ /*str init */) {')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TODO tmp hack for 0 pointers init
|
|
||||||
// &User{!} ==> 0
|
|
||||||
if p.tok == .not {
|
|
||||||
p.next()
|
|
||||||
p.gen('0')
|
|
||||||
p.check(.rcbr)
|
|
||||||
return typ
|
|
||||||
}
|
|
||||||
p.is_alloc = true
|
|
||||||
//println('setting is_alloc=true (ret $typ)')
|
|
||||||
p.gen('($t.name*)memdup(&($t.name) {')
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
mut did_gen_something := false
|
mut did_gen_something := false
|
||||||
// Loop thru all struct init keys and assign values
|
// Loop thru all struct init keys and assign values
|
||||||
// u := User{age:20, name:'bob'}
|
// u := User{age:20, name:'bob'}
|
||||||
|
@ -3763,12 +3735,10 @@ fn (p mut Parser) js_decode() string {
|
||||||
|
|
||||||
fn (p mut Parser) attribute() {
|
fn (p mut Parser) attribute() {
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
if p.tok == .key_interface {
|
p.attr = p.check_name()
|
||||||
p.check(.key_interface)
|
if p.tok == .colon {
|
||||||
p.check(.colon)
|
p.check(.colon)
|
||||||
p.attr = 'interface:' + p.check_name()
|
p.attr = p.attr + ':' + p.check_name()
|
||||||
} else {
|
|
||||||
p.attr = p.check_name()
|
|
||||||
}
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
if p.tok == .func || (p.tok == .key_pub && p.peek() == .func) {
|
if p.tok == .func || (p.tok == .key_pub && p.peek() == .func) {
|
||||||
|
|
|
@ -54,6 +54,7 @@ enum TypeCategory {
|
||||||
union_ // 5
|
union_ // 5
|
||||||
c_struct
|
c_struct
|
||||||
c_typedef
|
c_typedef
|
||||||
|
objc_interface // 8 Objective C @interface
|
||||||
array
|
array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,6 +608,11 @@ fn (p mut Parser) _check_types(got_, expected_ string, throw bool) bool {
|
||||||
// if expected == 'T' || expected.contains('<T>') {
|
// if expected == 'T' || expected.contains('<T>') {
|
||||||
// return true
|
// return true
|
||||||
// }
|
// }
|
||||||
|
// TODO fn hack
|
||||||
|
if got.starts_with('fn ') && (expected.ends_with('fn') ||
|
||||||
|
expected.ends_with('Fn')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
// Allow pointer arithmetic
|
// Allow pointer arithmetic
|
||||||
if expected=='void*' && got=='int' {
|
if expected=='void*' && got=='int' {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -42,7 +42,7 @@ fn (ctx &Context) draw() {
|
||||||
ctx.gg.draw_line(Size / 2, 0, Size / 2, Size) // y axis
|
ctx.gg.draw_line(Size / 2, 0, Size / 2, Size) // y axis
|
||||||
center := f64(Size / 2)
|
center := f64(Size / 2)
|
||||||
for x := -10.0; x <= 10.0; x += 0.002 {
|
for x := -10.0; x <= 10.0; x += 0.002 {
|
||||||
y := x * x + 1
|
y := x * x - 1
|
||||||
//y := (x + 3) * (x + 3) - 1
|
//y := (x + 3) * (x + 3) - 1
|
||||||
//y := math.sqrt(30.0 - x * x)
|
//y := math.sqrt(30.0 - x * x)
|
||||||
ctx.gg.draw_rect(center + x * Scale, center - y * Scale, 1, 1, gx.Black)
|
ctx.gg.draw_rect(center + x * Scale, center - y * Scale, 1, 1, gx.Black)
|
||||||
|
|
|
@ -32,6 +32,6 @@
|
||||||
+ o(log n) type lookup
|
+ o(log n) type lookup
|
||||||
- prebuilt binaries for all platforms
|
- prebuilt binaries for all platforms
|
||||||
- fix interfaces
|
- fix interfaces
|
||||||
- `none` keyword for optionals
|
+ `none` keyword for optionals
|
||||||
- table: migrate all find*** functions to optionals
|
+ table: migrate all find*** functions to optionals
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ module darwin
|
||||||
struct C.NSString { }
|
struct C.NSString { }
|
||||||
|
|
||||||
// macOS and iOS helpers
|
// macOS and iOS helpers
|
||||||
fn nsstring(s string) *NSString {
|
pub fn nsstring(s string) *NSString {
|
||||||
// #return @"" ;
|
// #return @"" ;
|
||||||
// println('ns $s len=$s.len')
|
// println('ns $s len=$s.len')
|
||||||
# return [ [ NSString alloc ] initWithBytesNoCopy:s.str length:s.len
|
# return [ [ NSString alloc ] initWithBytesNoCopy:s.str length:s.len
|
||||||
|
|
|
@ -771,7 +771,8 @@ pub fn file_last_mod_unix(path string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn log(s string) {
|
pub fn log(s string) {
|
||||||
|
println('os.log: ' + s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flush_stdout() {
|
pub fn flush_stdout() {
|
||||||
|
|
|
@ -15,6 +15,7 @@ struct User {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
|
mut:
|
||||||
first_name ui.TextBox
|
first_name ui.TextBox
|
||||||
last_name ui.TextBox
|
last_name ui.TextBox
|
||||||
age ui.TextBox
|
age ui.TextBox
|
||||||
|
@ -23,6 +24,61 @@ struct Context {
|
||||||
txt_pos int
|
txt_pos int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct Window {
|
||||||
|
width: 500
|
||||||
|
height: 300
|
||||||
|
title: 'Users'
|
||||||
|
content: Layout {
|
||||||
|
[
|
||||||
|
TextBox {
|
||||||
|
placeholder: 'First name'
|
||||||
|
},
|
||||||
|
TextBox {
|
||||||
|
placeholder: 'Last name'
|
||||||
|
},
|
||||||
|
TextBox {
|
||||||
|
placeholder: 'Age'
|
||||||
|
},
|
||||||
|
Button {
|
||||||
|
title: 'Add user'
|
||||||
|
onclick: btn_click
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
draw: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Window {
|
||||||
|
width: 500
|
||||||
|
height: 300
|
||||||
|
title: 'Users'
|
||||||
|
VLayout {
|
||||||
|
TextBox {
|
||||||
|
placeholder: 'First name'
|
||||||
|
}
|
||||||
|
TextBox {
|
||||||
|
placeholder: 'Last name'
|
||||||
|
}
|
||||||
|
TextBox {
|
||||||
|
placeholder: 'Age'
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
title: 'Add user'
|
||||||
|
onclick: btn_click
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw: draw_fn
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
*/
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
mut ctx := &Context {
|
mut ctx := &Context {
|
||||||
txt_pos: 10
|
txt_pos: 10
|
||||||
|
@ -45,30 +101,30 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO replace with `fn (ctx mut Context) btn_click() {`
|
// TODO replace with `fn (ctx mut Context) btn_click() {`
|
||||||
fn btn_click(_ctx *Context) {
|
fn btn_click(_ctx &Context) {
|
||||||
mut ctx = _ctx// TODO hack
|
mut ctx := _ctx// TODO hack
|
||||||
ctx.users << User {
|
ctx.users << User {
|
||||||
first_name: ctx.first_name.text()
|
first_name: ctx.first_name.text()
|
||||||
last_name: ctx.last_name.text()
|
last_name: ctx.last_name.text()
|
||||||
age: ctx.age.text().to_i()
|
age: ctx.age.text().int()
|
||||||
}
|
}
|
||||||
ctx.window.refresh()
|
ctx.window.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO replace with `fn (ctx mut Context) draw() {`
|
// TODO replace with `fn (ctx mut Context) draw() {`
|
||||||
fn draw(ctx *Context) {
|
fn draw(ctx &Context) {
|
||||||
for i, user in ctx.users {
|
for i, user in ctx.users {
|
||||||
x := 10
|
x := 10
|
||||||
y := 10 + i * CELL_HEIGHT
|
y := 10 + i * CELL_HEIGHT
|
||||||
// Outer border
|
// Outer border
|
||||||
gx.draw_empty_rect(x, y, TABLE_WIDTH, CELL_HEIGHT, gx.GRAY)
|
ui.draw_empty_rect(x, y, TABLE_WIDTH, CELL_HEIGHT, gx.Gray)
|
||||||
// Vertical separators
|
// Vertical separators
|
||||||
gx.draw_line(x + CELL_WIDTH, y, x + CELL_WIDTH, y + CELL_HEIGHT)
|
ui.draw_line(x + CELL_WIDTH, y, x + CELL_WIDTH, y + CELL_HEIGHT, gx.Gray)
|
||||||
gx.draw_line(x + CELL_WIDTH * 2, y, x + CELL_WIDTH * 2, y + CELL_HEIGHT)
|
ui.draw_line(x + CELL_WIDTH * 2, y, x + CELL_WIDTH * 2, y + CELL_HEIGHT, gx.Gray)
|
||||||
// Text values
|
// Text values
|
||||||
gx.draw_text_def(x + 5, y + 5, user.first_name)
|
ui.draw_text_def(x + 5, y + 5, user.first_name)
|
||||||
gx.draw_text_def(x + 5 + CELL_WIDTH, y + 5, user.last_name)
|
ui.draw_text_def(x + 5 + CELL_WIDTH, y + 5, user.last_name)
|
||||||
gx.draw_text_def(x + 5 + CELL_WIDTH * 2, y + 5, user.age.str())
|
ui.draw_text_def(x + 5 + CELL_WIDTH * 2, y + 5, user.age.str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,5 +28,3 @@ pub fn reg_key_vid() {
|
||||||
#RegisterEventHotKey(kVK_ANSI_1, cmdKey, gMyHotKeyID,
|
#RegisterEventHotKey(kVK_ANSI_1, cmdKey, gMyHotKeyID,
|
||||||
#GetApplicationEventTarget(), 0, &gMyHotKeyRef);
|
#GetApplicationEventTarget(), 0, &gMyHotKeyRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue