unsafe keyword + make array.free() an unsafe method
parent
f7c00b8180
commit
1b518c158b
|
@ -234,6 +234,7 @@ pub fn (a array) clone() array {
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub fn (a []int) free() {
|
//pub fn (a []int) free() {
|
||||||
|
[unsafe_fn]
|
||||||
pub fn (a array) free() {
|
pub fn (a array) free() {
|
||||||
//if a.is_slice {
|
//if a.is_slice {
|
||||||
//return
|
//return
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright (c) 2019 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 compiler
|
||||||
|
|
||||||
|
fn (p mut Parser) enum_decl(_enum_name string) {
|
||||||
|
mut enum_name := _enum_name
|
||||||
|
// Specify full type name
|
||||||
|
if !p.builtin_mod && p.mod != 'main' {
|
||||||
|
enum_name = p.prepend_mod(enum_name)
|
||||||
|
}
|
||||||
|
// Skip empty enums
|
||||||
|
if enum_name != 'int' && !p.first_pass() {
|
||||||
|
p.cgen.typedefs << 'typedef int $enum_name;'
|
||||||
|
}
|
||||||
|
p.check(.lcbr)
|
||||||
|
mut val := 0
|
||||||
|
mut fields := []string
|
||||||
|
for p.tok == .name {
|
||||||
|
field := p.check_name()
|
||||||
|
fields << field
|
||||||
|
p.fgenln('')
|
||||||
|
name := '${mod_gen_name(p.mod)}__${enum_name}_$field'
|
||||||
|
if p.pass == .main {
|
||||||
|
p.cgen.consts << '#define $name $val'
|
||||||
|
}
|
||||||
|
if p.tok == .comma {
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
// !!!! NAME free
|
||||||
|
if p.first_pass() {
|
||||||
|
p.table.register_const(name, enum_name, p.mod)
|
||||||
|
}
|
||||||
|
val++
|
||||||
|
}
|
||||||
|
p.table.register_type2(Type {
|
||||||
|
name: enum_name
|
||||||
|
mod: p.mod
|
||||||
|
parent: 'int'
|
||||||
|
cat: TypeCategory.enum_
|
||||||
|
enum_vals: fields.clone()
|
||||||
|
})
|
||||||
|
p.check(.rcbr)
|
||||||
|
p.fgenln('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (p mut Parser) check_enum_member_access() {
|
||||||
|
T := p.find_type(p.expected_type)
|
||||||
|
if T.cat == .enum_ {
|
||||||
|
p.check(.dot)
|
||||||
|
val := p.check_name()
|
||||||
|
// Make sure this enum value exists
|
||||||
|
if !T.has_enum_val(val) {
|
||||||
|
p.error('enum `$T.name` does not have value `$val`')
|
||||||
|
}
|
||||||
|
p.gen(mod_gen_name(T.mod) + '__' + p.expected_type + '_' + val)
|
||||||
|
} else {
|
||||||
|
p.error('`$T.name` is not an enum')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ mut:
|
||||||
is_method bool
|
is_method bool
|
||||||
returns_error bool
|
returns_error bool
|
||||||
is_decl bool // type myfn fn(int, int)
|
is_decl bool // type myfn fn(int, int)
|
||||||
|
is_unsafe bool
|
||||||
defer_text []string
|
defer_text []string
|
||||||
is_generic bool
|
is_generic bool
|
||||||
type_pars []string
|
type_pars []string
|
||||||
|
@ -158,10 +159,11 @@ fn (p mut Parser) clear_vars() {
|
||||||
p.var_idx = 0
|
p.var_idx = 0
|
||||||
if p.local_vars.len > 0 {
|
if p.local_vars.len > 0 {
|
||||||
if p.pref.autofree {
|
if p.pref.autofree {
|
||||||
p.local_vars.free()
|
//p.local_vars.free()
|
||||||
}
|
}
|
||||||
p.local_vars = []Var
|
p.local_vars = []Var
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function signatures are added to the top of the .c file in the first run.
|
// Function signatures are added to the top of the .c file in the first run.
|
||||||
|
@ -184,6 +186,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
mut f := Fn{
|
mut f := Fn{
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
is_public: p.tok == .key_pub
|
is_public: p.tok == .key_pub
|
||||||
|
is_unsafe: p.attr == 'unsafe_fn'
|
||||||
}
|
}
|
||||||
is_live := p.attr == 'live' && !p.pref.is_so && p.pref.is_live
|
is_live := p.attr == 'live' && !p.pref.is_so && p.pref.is_live
|
||||||
if p.attr == 'live' && p.first_pass() && !p.pref.is_live && !p.pref.is_so {
|
if p.attr == 'live' && p.first_pass() && !p.pref.is_live && !p.pref.is_so {
|
||||||
|
@ -631,6 +634,9 @@ fn (p mut Parser) async_fn_call(f Fn, method_ph int, receiver_var, receiver_type
|
||||||
|
|
||||||
// p.tok == fn_name
|
// p.tok == fn_name
|
||||||
fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type string) {
|
fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type string) {
|
||||||
|
if f.is_unsafe && !p.builtin_mod && !p.inside_unsafe {
|
||||||
|
p.error('you are calling an unsafe function outside of an unsafe block')
|
||||||
|
}
|
||||||
if !f.is_public && !f.is_c && !p.pref.is_test && !f.is_interface && f.mod != p.mod {
|
if !f.is_public && !f.is_c && !p.pref.is_test && !f.is_interface && f.mod != p.mod {
|
||||||
if f.name == 'contains' {
|
if f.name == 'contains' {
|
||||||
println('use `value in numbers` instead of `numbers.contains(value)`')
|
println('use `value in numbers` instead of `numbers.contains(value)`')
|
||||||
|
|
|
@ -117,6 +117,7 @@ pub mut:
|
||||||
pub fn (v mut V) finalize_compilation(){
|
pub fn (v mut V) finalize_compilation(){
|
||||||
// TODO remove
|
// TODO remove
|
||||||
if v.pref.autofree {
|
if v.pref.autofree {
|
||||||
|
/*
|
||||||
println('started freeing v struct')
|
println('started freeing v struct')
|
||||||
v.table.typesmap.free()
|
v.table.typesmap.free()
|
||||||
v.table.obf_ids.free()
|
v.table.obf_ids.free()
|
||||||
|
@ -131,6 +132,7 @@ pub fn (v mut V) finalize_compilation(){
|
||||||
free(v.table)
|
free(v.table)
|
||||||
//for p in parsers {}
|
//for p in parsers {}
|
||||||
println('done!')
|
println('done!')
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ mut:
|
||||||
inside_if_expr bool
|
inside_if_expr bool
|
||||||
inside_unwrapping_match_statement bool
|
inside_unwrapping_match_statement bool
|
||||||
inside_return_expr bool
|
inside_return_expr bool
|
||||||
|
inside_unsafe bool
|
||||||
is_struct_init bool
|
is_struct_init bool
|
||||||
if_expr_cnt int
|
if_expr_cnt int
|
||||||
for_expr_cnt int // to detect whether `continue` can be used
|
for_expr_cnt int // to detect whether `continue` can be used
|
||||||
|
@ -839,47 +840,6 @@ fn (p mut Parser) struct_decl() {
|
||||||
p.fgenln('\n')
|
p.fgenln('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) enum_decl(_enum_name string) {
|
|
||||||
mut enum_name := _enum_name
|
|
||||||
// Specify full type name
|
|
||||||
if !p.builtin_mod && p.mod != 'main' {
|
|
||||||
enum_name = p.prepend_mod(enum_name)
|
|
||||||
}
|
|
||||||
// Skip empty enums
|
|
||||||
if enum_name != 'int' && !p.first_pass() {
|
|
||||||
p.cgen.typedefs << 'typedef int $enum_name;'
|
|
||||||
}
|
|
||||||
p.check(.lcbr)
|
|
||||||
mut val := 0
|
|
||||||
mut fields := []string
|
|
||||||
for p.tok == .name {
|
|
||||||
field := p.check_name()
|
|
||||||
fields << field
|
|
||||||
p.fgenln('')
|
|
||||||
name := '${mod_gen_name(p.mod)}__${enum_name}_$field'
|
|
||||||
if p.pass == .main {
|
|
||||||
p.cgen.consts << '#define $name $val'
|
|
||||||
}
|
|
||||||
if p.tok == .comma {
|
|
||||||
p.next()
|
|
||||||
}
|
|
||||||
// !!!! NAME free
|
|
||||||
if p.first_pass() {
|
|
||||||
p.table.register_const(name, enum_name, p.mod)
|
|
||||||
}
|
|
||||||
val++
|
|
||||||
}
|
|
||||||
p.table.register_type2(Type {
|
|
||||||
name: enum_name
|
|
||||||
mod: p.mod
|
|
||||||
parent: 'int'
|
|
||||||
cat: TypeCategory.enum_
|
|
||||||
enum_vals: fields.clone()
|
|
||||||
})
|
|
||||||
p.check(.rcbr)
|
|
||||||
p.fgenln('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
// check_name checks for a name token and returns its literal
|
// check_name checks for a name token and returns its literal
|
||||||
fn (p mut Parser) check_name() string {
|
fn (p mut Parser) check_name() string {
|
||||||
name := p.lit
|
name := p.lit
|
||||||
|
@ -1316,6 +1276,14 @@ fn (p mut Parser) statement(add_semi bool) string {
|
||||||
case TokenKind.hash:
|
case TokenKind.hash:
|
||||||
p.chash()
|
p.chash()
|
||||||
return ''
|
return ''
|
||||||
|
case TokenKind.key_unsafe:
|
||||||
|
p.next()
|
||||||
|
p.inside_unsafe = true
|
||||||
|
p.check(.lcbr)
|
||||||
|
p.genln('{')
|
||||||
|
p.statements()
|
||||||
|
p.inside_unsafe = false
|
||||||
|
//p.check(.rcbr)
|
||||||
case TokenKind.dollar:
|
case TokenKind.dollar:
|
||||||
p.comp_time()
|
p.comp_time()
|
||||||
case TokenKind.key_if:
|
case TokenKind.key_if:
|
||||||
|
@ -1828,6 +1796,10 @@ fn (p mut Parser) name_expr() string {
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
val := p.lit
|
val := p.lit
|
||||||
|
if !enum_type.has_enum_val(val) {
|
||||||
|
p.error('enum `$enum_type.name` does not have value `$val`')
|
||||||
|
}
|
||||||
|
|
||||||
// println('enum val $val')
|
// println('enum val $val')
|
||||||
p.gen(mod_gen_name(enum_type.mod) + '__' + enum_type.name + '_' + val)// `color = main__Color_green`
|
p.gen(mod_gen_name(enum_type.mod) + '__' + enum_type.name + '_' + val)// `color = main__Color_green`
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -1910,21 +1882,6 @@ fn (p mut Parser) get_struct_type(name_ string, is_c bool, is_ptr bool) string {
|
||||||
return p.struct_init(name)
|
return p.struct_init(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) check_enum_member_access() {
|
|
||||||
T := p.find_type(p.expected_type)
|
|
||||||
if T.cat == .enum_ {
|
|
||||||
p.check(.dot)
|
|
||||||
val := p.check_name()
|
|
||||||
// Make sure this enum value exists
|
|
||||||
if !T.has_enum_val(val) {
|
|
||||||
p.error('enum `$T.name` does not have value `$val`')
|
|
||||||
}
|
|
||||||
p.gen(mod_gen_name(T.mod) + '__' + p.expected_type + '_' + val)
|
|
||||||
} else {
|
|
||||||
p.error('`$T.name` is not an enum')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (p mut Parser) get_var_type(name string, is_ptr bool, is_deref bool) string {
|
fn (p mut Parser) get_var_type(name string, is_ptr bool, is_deref bool) string {
|
||||||
v := p.find_var_check_new_var(name) or { return "" }
|
v := p.find_var_check_new_var(name) or { return "" }
|
||||||
if name == '_' {
|
if name == '_' {
|
||||||
|
|
|
@ -110,6 +110,7 @@ enum TokenKind {
|
||||||
key_union
|
key_union
|
||||||
key_pub
|
key_pub
|
||||||
key_static
|
key_static
|
||||||
|
key_unsafe
|
||||||
keyword_end
|
keyword_end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +211,7 @@ fn build_token_str() []string {
|
||||||
s[TokenKind.key_break] = 'break'
|
s[TokenKind.key_break] = 'break'
|
||||||
s[TokenKind.key_import] = 'import'
|
s[TokenKind.key_import] = 'import'
|
||||||
s[TokenKind.key_embed] = 'embed'
|
s[TokenKind.key_embed] = 'embed'
|
||||||
|
s[TokenKind.key_unsafe] = 'unsafe'
|
||||||
//Tokens[key_typeof] = 'typeof'
|
//Tokens[key_typeof] = 'typeof'
|
||||||
s[TokenKind.key_default] = 'default'
|
s[TokenKind.key_default] = 'default'
|
||||||
s[TokenKind.key_enum] = 'enum'
|
s[TokenKind.key_enum] = 'enum'
|
||||||
|
|
Loading…
Reference in New Issue