all: rune type for `` literals

pull/6232/head
Alexander Medvednikov 2020-08-27 06:46:18 +02:00
parent 99dd72efea
commit 6921d46185
17 changed files with 173 additions and 108 deletions

View File

@ -17,4 +17,5 @@
- struct and interface embedding - struct and interface embedding
- vfmt: fix common errors automatically to save time (make vars mutable and vice versa, add missing imports etc) - vfmt: fix common errors automatically to save time (make vars mutable and vice versa, add missing imports etc)
- method expressions with an explicit receiver as the first argument - method expressions with an explicit receiver as the first argument
- fix all remaining generics issues (`foo(5)` instead of `foo<int>(5)` etc)

View File

@ -43,6 +43,7 @@ fn main() {
create_window: true create_window: true
frame_fn: frame frame_fn: frame
bg_color: gx.white bg_color: gx.white
font_path: gg.system_font_path()
}) })
// window.onkeydown(key_down) // window.onkeydown(key_down)
println('Starting the game loop...') println('Starting the game loop...')
@ -56,6 +57,7 @@ fn main() {
[live] [live]
fn frame (mut game Game) { fn frame (mut game Game) {
game.gg.begin() game.gg.begin()
game.gg.draw_text_def(10, 5, 'Modify examples/hot_reload/bounce.v to get instant updates')
game.gg.draw_rect(game.x, game.y, width, width, gx.blue) game.gg.draw_rect(game.x, game.y, width, width, gx.blue)
game.gg.draw_rect(window_width - width - game.x + 10, 200 - game.y + width, width, width, gx.rgb(228, 10, 55)) game.gg.draw_rect(window_width - width - game.x + 10, 200 - game.y + width, width, width, gx.rgb(228, 10, 55))
game.gg.draw_rect(game.x - 25, 250 - game.y, width, width, gx.rgb(28, 240, 55)) game.gg.draw_rect(game.x - 25, 250 - game.y, width, width, gx.rgb(28, 240, 55))

View File

@ -607,6 +607,15 @@ pub fn (a []byte) index(v byte) int {
return -1 return -1
} }
pub fn (a []rune) index(v rune) int {
for i in 0..a.len {
if a[i] == v {
return i
}
}
return -1
}
// []char.index returns the index of the first element equal to the given value, // []char.index returns the index of the first element equal to the given value,
// or -1 if the value is not found in the array. // or -1 if the value is not found in the array.
// TODO is `char` type yet in the language? // TODO is `char` type yet in the language?

View File

@ -5,4 +5,15 @@ fn test_clone() {
assert b[0] == 0 assert b[0] == 0
assert b[1] == 1 assert b[1] == 1
assert b[2] == 2 assert b[2] == 2
println(b[1].str() )
println(typeof(`A`))
x := rune(`A`)
assert x.str() == 'A'
assert typeof(x) == 'rune'
//
y := `Z`
assert typeof(y) == 'rune'
assert y.str() == 'Z'
// assert b[1].str() == '1' TODO
} }

View File

@ -368,80 +368,21 @@ pub fn (nn byteptr) str() string {
return u64(nn).hex() return u64(nn).hex()
} }
// ----- utilities functions ----- pub fn (b byte) str() string {
// TODO
/* //return int(b).str_l(7)
pub fn (c rune) str() string {
fst_byte := int(c)>>8 * 3 & 0xff
len := utf8_char_len(fst_byte)
mut str := string{
len: len
str: malloc(len + 1)
}
for i in 0..len {
str.str[i] = int(c)>>8 * (3 - i) & 0xff
}
str.str[len] = `\0`
return str
}
*/
pub fn (c byte) str() string {
mut str := string{ mut str := string{
str: malloc(2) str: malloc(2)
len: 1 len: 1
} }
unsafe { unsafe {
str.str[0] = c str.str[0] = b
str.str[1] = `\0` str.str[1] = `\0`
} }
//println(str)
return str return str
} }
/*
type rune = int
pub fn (r rune) str() string {
mut str := string{
str: malloc(2)
len: 1
}
unsafe {
str.str[0] = r
str.str[1] = `\0`
}
return str
}
*/
pub fn (c byte) is_capital() bool {
return c >= `A` && c <= `Z`
}
pub fn (b []byte) clone() []byte {
mut res := []byte{len: b.len}
//mut res := make([]byte, {repeat:b.len})
for i in 0..b.len {
res[i] = b[i]
}
return res
}
// TODO remove this once runes are implemented
pub fn (b []byte) bytestr() string {
return bytes2string(b)
}
// TODO copy pasted from builder.v
fn bytes2string(b []byte) string {
mut copy := b.clone()
copy << `\0`
res := tos(copy.data, copy.len-1)
return res
}
// TODO generic // TODO generic
pub fn (a []byte) contains(val byte) bool { pub fn (a []byte) contains(val byte) bool {
for aa in a { for aa in a {

View File

@ -0,0 +1,54 @@
// 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 builtin
type rune = int
pub fn (c rune) str() string {
return utf32_to_str(u32(c))
/*
unsafe {
fst_byte := int(c)>>8 * 3 & 0xff
len := utf8_char_len(byte(fst_byte))
println('len=$len')
mut str := string{
len: len
str: malloc(len + 1)
}
for i in 0..len {
str.str[i] = byte(int(c)>>8 * (3 - i) & 0xff)
}
str.str[len] = `\0`
println(str)
return str
}
*/
}
// Define this on byte as well, so that we can do `s[0].is_capital()`
pub fn (c byte) is_capital() bool {
return c >= `A` && c <= `Z`
}
pub fn (b []byte) clone() []byte {
mut res := []byte{len: b.len}
//mut res := make([]byte, {repeat:b.len})
for i in 0..b.len {
res[i] = b[i]
}
return res
}
// TODO remove this once runes are implemented
pub fn (b []byte) bytestr() string {
return bytes2string(b)
}
// TODO copy pasted from builder.v
fn bytes2string(b []byte) string {
mut copy := b.clone()
copy << `\0`
res := tos(copy.data, copy.len-1)
return res
}

View File

@ -504,7 +504,7 @@ fn test_bytes_to_string() {
} }
assert unsafe { buf.vstring() } == 'hello' assert unsafe { buf.vstring() } == 'hello'
assert unsafe { buf.vstring_with_len(2) } == 'he' assert unsafe { buf.vstring_with_len(2) } == 'he'
bytes := [`h`, `e`, `l`, `l`, `o`] bytes := [byte(`h`), `e`, `l`, `l`, `o`]
assert bytes.bytestr() == 'hello' assert bytes.bytestr() == 'hello'
} }

View File

@ -163,3 +163,31 @@ pub fn (ctx &Context) text_size(s string) (int, int) {
return int((buf[2] - buf[0]) / ctx.scale), int((buf[3] - buf[1]) / ctx.scale) return int((buf[2] - buf[0]) / ctx.scale), int((buf[3] - buf[1]) / ctx.scale)
} }
pub fn system_font_path() string {
env_font := os.getenv('VUI_FONT')
if env_font != '' && os.exists(env_font) {
return env_font
}
$if windows {
return 'C:\\Windows\\Fonts\\arial.ttf'
}
mut fonts := ['Ubuntu-R.ttf', 'Arial.ttf', 'LiberationSans-Regular.ttf', 'NotoSans-Regular.ttf',
'FreeSans.ttf', 'DejaVuSans.ttf']
$if macos {
return '/System/Library/Fonts/SFNS.ttf'
//fonts = ['SFNS.ttf', 'SFNSText.ttf']
}
s := os.exec('fc-list') or { panic('failed to fetch system fonts') }
system_fonts := s.output.split('\n')
for line in system_fonts {
for font in fonts {
if line.contains(font) && line.contains(':') {
res := line.all_before(':')
println('Using font $res')
return res
}
}
}
panic('failed to init the font')
}

View File

@ -72,7 +72,8 @@ pub fn (f &File) read_bytes(size int) []byte {
// read_bytes_at reads an amount of bytes at the given position in the file // read_bytes_at reads an amount of bytes at the given position in the file
pub fn (f &File) read_bytes_at(size, pos int) []byte { pub fn (f &File) read_bytes_at(size, pos int) []byte {
mut arr := [`0`].repeat(size) //mut arr := [`0`].repeat(size)
mut arr := []byte{ len:size }
C.fseek(f.cfile, pos, C.SEEK_SET) C.fseek(f.cfile, pos, C.SEEK_SET)
nreadbytes := C.fread(arr.data, 1, size, f.cfile) nreadbytes := C.fread(arr.data, 1, size, f.cfile)
C.fseek(f.cfile, 0, C.SEEK_SET) C.fseek(f.cfile, 0, C.SEEK_SET)

View File

@ -16,7 +16,7 @@ pub fn read_bytes(path string) ?[]byte {
C.fseek(fp, 0, C.SEEK_END) C.fseek(fp, 0, C.SEEK_END)
fsize := C.ftell(fp) fsize := C.ftell(fp)
C.rewind(fp) C.rewind(fp)
mut res := [`0`].repeat(fsize) mut res := [byte(`0`)].repeat(fsize)
nr_read_elements := C.fread(res.data, fsize, 1, fp) nr_read_elements := C.fread(res.data, fsize, 1, fp)
C.fclose(fp) C.fclose(fp)
return res[0..nr_read_elements * fsize] return res[0..nr_read_elements * fsize]

View File

@ -207,7 +207,7 @@ pub fn (re RE) get_parse_error_string(err int) string {
// utf8_str convert and utf8 sequence to a printable string // utf8_str convert and utf8 sequence to a printable string
[inline] [inline]
fn utf8_str(ch u32) string { fn utf8_str(ch rune) string {
mut i := 4 mut i := 4
mut res := "" mut res := ""
for i > 0 { for i > 0 {
@ -233,33 +233,33 @@ fn simple_log(txt string) {
pub type FnValidator fn (byte) bool pub type FnValidator fn (byte) bool
struct Token{ struct Token{
mut: mut:
ist u32 = u32(0) ist rune
// char // char
ch u32 = u32(0) // char of the token if any ch rune // char of the token if any
ch_len byte = byte(0) // char len ch_len byte // char len
// Quantifiers / branch // Quantifiers / branch
rep_min int = 0 // used also for jump next in the OR branch [no match] pc jump rep_min int // used also for jump next in the OR branch [no match] pc jump
rep_max int = 0 // used also for jump next in the OR branch [ match] pc jump rep_max int // used also for jump next in the OR branch [ match] pc jump
greedy bool = false // greedy quantifier flag greedy bool // greedy quantifier flag
// Char class // Char class
cc_index int = -1 cc_index int = -1
// counters for quantifier check (repetitions) // counters for quantifier check (repetitions)
rep int = 0 rep int
// validator function pointer // validator function pointer
validator FnValidator validator FnValidator
// groups variables // groups variables
group_rep int = 0 // repetition of the group group_rep int // repetition of the group
group_id int = -1 // id of the group group_id int = -1 // id of the group
goto_pc int = -1 // jump to this PC if is needed goto_pc int = -1 // jump to this PC if is needed
// OR flag for the token // OR flag for the token
next_is_or bool = false // true if the next token is an OR next_is_or bool // true if the next token is an OR
} }
[inline] [inline]
@ -380,7 +380,7 @@ Backslashes chars
*/ */
struct BslsStruct { struct BslsStruct {
ch u32 // meta char ch rune // meta char
validator FnValidator // validator function pointer validator FnValidator // validator function pointer
} }
@ -466,8 +466,8 @@ const(
struct CharClass { struct CharClass {
mut: mut:
cc_type int = cc_null // type of cc token cc_type int = cc_null // type of cc token
ch0 u32 = u32(0) // first char of the interval a-b a in this case ch0 rune // first char of the interval a-b a in this case
ch1 u32 = u32(0) // second char of the interval a-b b in this case ch1 rune // second char of the interval a-b b in this case
validator FnValidator // validator function pointer validator FnValidator // validator function pointer
} }
@ -540,7 +540,7 @@ fn (re RE) get_char_class(pc int) string {
return tos_clone( buf_ptr ) return tos_clone( buf_ptr )
} }
fn (re RE) check_char_class(pc int, ch u32) bool { fn (re RE) check_char_class(pc int, ch rune) bool {
mut cc_i := re.prog[pc].cc_index mut cc_i := re.prog[pc].cc_index
for cc_i >= 0 && cc_i < re.cc.len && re.cc[cc_i].cc_type != cc_end { for cc_i >= 0 && cc_i < re.cc.len && re.cc[cc_i].cc_type != cc_end {
if re.cc[cc_i].cc_type == cc_bsls { if re.cc[cc_i].cc_type == cc_bsls {
@ -557,7 +557,7 @@ fn (re RE) check_char_class(pc int, ch u32) bool {
} }
// parse_char_class return (index, str_len, cc_type) of a char class [abcm-p], char class start after the [ char // parse_char_class return (index, str_len, cc_type) of a char class [abcm-p], char class start after the [ char
fn (mut re RE) parse_char_class(in_txt string, in_i int) (int, int, u32) { fn (mut re RE) parse_char_class(in_txt string, in_i int) (int, int, rune) {
mut status := CharClass_parse_state.start mut status := CharClass_parse_state.start
mut i := in_i mut i := in_i
@ -1493,14 +1493,14 @@ pub fn (mut re RE) match_base(in_txt byteptr, in_txt_len int ) (int,int) {
mut first_match := -1 //index of the first match mut first_match := -1 //index of the first match
mut i := 0 // source string index mut i := 0 // source string index
mut ch := u32(0) // examinated char mut ch := rune(0) // examinated char
mut char_len := 0 // utf8 examinated char len mut char_len := 0 // utf8 examinated char len
mut m_state := Match_state.start // start point for the matcher FSM mut m_state := Match_state.start // start point for the matcher FSM
mut pc := -1 // program counter mut pc := -1 // program counter
mut state := StateObj{} // actual state mut state := StateObj{} // actual state
mut ist := u32(0) // actual instruction mut ist := rune(0) // actual instruction
mut l_ist := u32(0) // last matched instruction mut l_ist :=rune(0) // last matched instruction
mut group_stack := [-1].repeat(re.group_max) mut group_stack := [-1].repeat(re.group_max)
mut group_data := [-1].repeat(re.group_max) mut group_data := [-1].repeat(re.group_max)

View File

@ -180,7 +180,7 @@ NOTE: #TOFIX need one char after the last char of the number
fn parser(s string) (int,PrepNumber) { fn parser(s string) (int,PrepNumber) {
mut state := fsm_a mut state := fsm_a
mut digx := 0 mut digx := 0
mut c := ` ` // initial value for kicking off the state machine mut c := byte(` `) // initial value for kicking off the state machine
mut result := parser_ok mut result := parser_ok
mut expneg := false mut expneg := false
mut expexp := 0 mut expexp := 0
@ -192,7 +192,8 @@ fn parser(s string) (int,PrepNumber) {
// skip starting spaces // skip starting spaces
fsm_a { fsm_a {
if is_space(c) == true { if is_space(c) == true {
c = s[i++] c = s[i]
i++
} }
else { else {
state = fsm_b state = fsm_b
@ -202,12 +203,13 @@ fn parser(s string) (int,PrepNumber) {
fsm_b { fsm_b {
state = fsm_c state = fsm_c
if c == c_plus { if c == c_plus {
c = s[i++] c = s[i]
//i++ i++
} }
else if c == c_minus { else if c == c_minus {
pn.negative = true pn.negative = true
c = s[i++] c = s[i]
i++
} }
else if is_digit(c) { else if is_digit(c) {
} }

View File

@ -203,7 +203,7 @@ pub fn f64_to_str_lnd(f f64, dec_digit int) string {
*/ */
pub struct BF_param { pub struct BF_param {
pad_ch byte = ` ` // padding char pad_ch byte = byte(` `) // padding char
len0 int = -1 // default len for whole the number or string len0 int = -1 // default len for whole the number or string
len1 int = 6 // number of decimal digits, if needed len1 int = 6 // number of decimal digits, if needed
positive bool = true // mandatory: the sign of the number passed positive bool = true // mandatory: the sign of the number passed
@ -438,7 +438,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
mut len0 := -1 // forced length, if -1 free length mut len0 := -1 // forced length, if -1 free length
mut len1 := -1 // decimal part for floats mut len1 := -1 // decimal part for floats
def_len1 := 6 // default value for len1 def_len1 := 6 // default value for len1
mut pad_ch := ` ` // pad char mut pad_ch := byte(` `) // pad char
mut th_separator := false // thousands separator flag mut th_separator := false // thousands separator flag
// prefix chars for Length field // prefix chars for Length field

View File

@ -52,7 +52,7 @@ pub fn (mut b Builder) go_back(n int) {
fn bytes2string(b []byte) string { fn bytes2string(b []byte) string {
mut copy := b.clone() mut copy := b.clone()
copy << `\0` copy << byte(`\0`)
res := tos(copy.data, copy.len-1) res := tos(copy.data, copy.len-1)
return res return res
} }

View File

@ -257,6 +257,11 @@ pub fn (mut c Checker) check_types(got, expected table.Type) bool {
return false return false
} }
if got.is_number() && expected.is_number() { if got.is_number() && expected.is_number() {
if got == table.rune_type && expected == table.byte_type {
return true
} else if expected == table.rune_type && got == table.byte_type {
return true
}
if c.promote_num(expected, got) != expected { if c.promote_num(expected, got) != expected {
// println('could not promote ${c.table.get_type_symbol(got).name} to ${c.table.get_type_symbol(expected).name}') // println('could not promote ${c.table.get_type_symbol(got).name} to ${c.table.get_type_symbol(expected).name}')
return false return false

View File

@ -1,6 +1,5 @@
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license that can be found in the LICENSE file.
// that can be found in the LICENSE file.
module checker module checker
import v.ast import v.ast
@ -260,7 +259,7 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
match node { match node {
ast.AliasTypeDecl { ast.AliasTypeDecl {
// TODO Replace `c.file.mod.name != 'time'` by `it.language != .v` once available // TODO Replace `c.file.mod.name != 'time'` by `it.language != .v` once available
if c.file.mod.name != 'time' { if c.file.mod.name != 'time' && c.file.mod.name != 'builtin' {
c.check_valid_pascal_case(node.name, 'type alias', node.pos) c.check_valid_pascal_case(node.name, 'type alias', node.pos)
} }
typ_sym := c.table.get_type_symbol(node.parent_type) typ_sym := c.table.get_type_symbol(node.parent_type)
@ -513,8 +512,10 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
.key_in, .not_in { .key_in, .not_in {
match right.kind { match right.kind {
.array { .array {
elem_type := right.array_info().elem_type
right_sym := c.table.get_type_symbol(c.table.mktyp(right.array_info().elem_type)) right_sym := c.table.get_type_symbol(c.table.mktyp(right.array_info().elem_type))
if left_default.kind != right_sym.kind { // if left_default.kind != right_sym.kind {
if !c.check_types(left_type, elem_type) {
c.error('the data type on the left of `$infix_expr.op.str()` (`$left.name`) does not match the array item type (`$right_sym.source_name`)', c.error('the data type on the left of `$infix_expr.op.str()` (`$left.name`) does not match the array item type (`$right_sym.source_name`)',
infix_expr.pos) infix_expr.pos)
} }
@ -2379,7 +2380,10 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
return c.chan_init(mut node) return c.chan_init(mut node)
} }
ast.CharLiteral { ast.CharLiteral {
return table.byte_type // return any_int, not rune, so that we can do "bytes << `A`" without a cast etc
// return table.any_int_type
return table.rune_type
// return table.byte_type
} }
ast.Comment { ast.Comment {
return table.void_type return table.void_type
@ -3032,7 +3036,9 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
mut last_expr := branch.stmts[branch.stmts.len - 1] as ast.ExprStmt mut last_expr := branch.stmts[branch.stmts.len - 1] as ast.ExprStmt
c.expected_type = former_expected_type c.expected_type = former_expected_type
last_expr.typ = c.expr(last_expr.expr) last_expr.typ = c.expr(last_expr.expr)
if last_expr.typ != node.typ { // if last_expr.typ != node.typ {
// if !c.check_types(node.typ, last_expr.typ) {
if !c.check_types(last_expr.typ, node.typ) {
if node.typ == table.void_type { if node.typ == table.void_type {
// first branch of if expression // first branch of if expression
node.is_expr = true node.is_expr = true

View File

@ -259,16 +259,20 @@ pub const (
// t_type_idx = 23 // t_type_idx = 23
any_flt_type_idx = 24 any_flt_type_idx = 24
any_int_type_idx = 25 any_int_type_idx = 25
sizet_type_idx = 26
rune_type_idx = 27
) )
pub const ( pub const (
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx, integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
u16_type_idx, u32_type_idx, u64_type_idx, any_int_type_idx] u16_type_idx, u32_type_idx, u64_type_idx, any_int_type_idx, rune_type_idx]
signed_integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx] signed_integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx]
unsigned_integer_type_idxs = [byte_type_idx, u16_type_idx, u32_type_idx, u64_type_idx] unsigned_integer_type_idxs = [byte_type_idx, u16_type_idx, u32_type_idx, u64_type_idx]
float_type_idxs = [f32_type_idx, f64_type_idx, any_flt_type_idx] float_type_idxs = [f32_type_idx, f64_type_idx, any_flt_type_idx]
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx, number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
u16_type_idx, u32_type_idx, u64_type_idx, f32_type_idx, f64_type_idx, any_int_type_idx, any_flt_type_idx] u16_type_idx, u32_type_idx, u64_type_idx, f32_type_idx, f64_type_idx, any_int_type_idx, any_flt_type_idx,
rune_type_idx,
]
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx] pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
string_type_idxs = [string_type_idx, ustring_type_idx] string_type_idxs = [string_type_idx, ustring_type_idx]
) )
@ -300,6 +304,7 @@ pub const (
// t_type = new_type(t_type_idx) // t_type = new_type(t_type_idx)
any_flt_type = new_type(any_flt_type_idx) any_flt_type = new_type(any_flt_type_idx)
any_int_type = new_type(any_int_type_idx) any_int_type = new_type(any_int_type_idx)
rune_type = new_type(rune_type_idx)
) )
pub const ( pub const (