vfmt fixes
parent
7bbaf432e6
commit
c35adbea91
|
@ -5,6 +5,7 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import strings
|
||||||
|
|
||||||
struct CGen {
|
struct CGen {
|
||||||
out os.File
|
out os.File
|
||||||
|
@ -20,6 +21,7 @@ struct CGen {
|
||||||
so_fns []string
|
so_fns []string
|
||||||
consts_init []string
|
consts_init []string
|
||||||
lines []string
|
lines []string
|
||||||
|
//buf strings.Builder
|
||||||
is_user bool
|
is_user bool
|
||||||
mut:
|
mut:
|
||||||
run Pass
|
run Pass
|
||||||
|
@ -37,11 +39,11 @@ fn new_cgen(out_name_c string) *CGen {
|
||||||
out := os.create(path) or {
|
out := os.create(path) or {
|
||||||
println('failed to create $path')
|
println('failed to create $path')
|
||||||
return &CGen{}
|
return &CGen{}
|
||||||
}
|
}
|
||||||
|
|
||||||
gen := &CGen {
|
gen := &CGen {
|
||||||
out_path: path
|
out_path: path
|
||||||
out: out
|
out: out
|
||||||
|
//buf: strings.new_builder(10000)
|
||||||
lines: _make(0, 1000, sizeof(string))
|
lines: _make(0, 1000, sizeof(string))
|
||||||
}
|
}
|
||||||
return gen
|
return gen
|
||||||
|
@ -144,7 +146,8 @@ fn (g mut CGen) set_placeholder2(pos int, val string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut CGen) insert_before(val string) {
|
fn (g mut CGen) insert_before(val string) {
|
||||||
g.lines.insert(g.lines.len - 1, val)
|
prev := g.lines[g.lines.len - 1]
|
||||||
|
g.lines[g.lines.len - 1] = '$prev \n $val \n'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut CGen) register_thread_fn(wrapper_name, wrapper_text, struct_text string) {
|
fn (g mut CGen) register_thread_fn(wrapper_name, wrapper_text, struct_text string) {
|
||||||
|
|
|
@ -44,11 +44,14 @@ enum OS {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Pass {
|
enum Pass {
|
||||||
// A very short pass that only looks at imports in the beginning of each file
|
// A very short pass that only looks at imports in the beginning of
|
||||||
|
// each file
|
||||||
imports
|
imports
|
||||||
// First pass, only parses and saves declarations (fn signatures, consts, types).
|
// First pass, only parses and saves declarations (fn signatures,
|
||||||
|
// consts, types).
|
||||||
// Skips function bodies.
|
// Skips function bodies.
|
||||||
// We need this because in V things can be used before they are declared.
|
// We need this because in V things can be used before they are
|
||||||
|
// declared.
|
||||||
decl
|
decl
|
||||||
// Second pass, parses function bodies and generates C or machine code.
|
// Second pass, parses function bodies and generates C or machine code.
|
||||||
main
|
main
|
||||||
|
@ -622,6 +625,7 @@ mut args := ''
|
||||||
if v.pref.build_mode != .build && (v.os == .linux || v.os == .freebsd || v.os == .openbsd ||
|
if v.pref.build_mode != .build && (v.os == .linux || v.os == .freebsd || v.os == .openbsd ||
|
||||||
v.os == .netbsd || v.os == .dragonfly) {
|
v.os == .netbsd || v.os == .dragonfly) {
|
||||||
a << '-lm -lpthread '
|
a << '-lm -lpthread '
|
||||||
|
// -ldl is a Linux only thing. BSDs have it in libc.
|
||||||
if v.os == .linux {
|
if v.os == .linux {
|
||||||
a << ' -ldl '
|
a << ' -ldl '
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,7 @@ fn (c mut V) new_parser(path string, run Pass) Parser {
|
||||||
fn (p mut Parser) next() {
|
fn (p mut Parser) next() {
|
||||||
p.prev_tok2 = p.prev_tok
|
p.prev_tok2 = p.prev_tok
|
||||||
p.prev_tok = p.tok
|
p.prev_tok = p.tok
|
||||||
|
p.scanner.prev_tok = p.tok
|
||||||
res := p.scanner.scan()
|
res := p.scanner.scan()
|
||||||
p.tok = res.tok
|
p.tok = res.tok
|
||||||
p.lit = res.lit
|
p.lit = res.lit
|
||||||
|
@ -144,7 +145,7 @@ fn (p mut Parser) parse() {
|
||||||
p.mod = fq_mod.replace('.', '_dot_')
|
p.mod = fq_mod.replace('.', '_dot_')
|
||||||
if p.run == .imports {
|
if p.run == .imports {
|
||||||
for p.tok == .key_import && p.peek() != .key_const {
|
for p.tok == .key_import && p.peek() != .key_const {
|
||||||
p.import_statement()
|
p.imports()
|
||||||
}
|
}
|
||||||
if p.table.imports.contains('builtin') {
|
if p.table.imports.contains('builtin') {
|
||||||
p.error('module `builtin` cannot be imported')
|
p.error('module `builtin` cannot be imported')
|
||||||
|
@ -160,7 +161,10 @@ fn (p mut Parser) parse() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO remove imported consts from the language
|
// TODO remove imported consts from the language
|
||||||
p.import_statement()
|
p.imports()
|
||||||
|
if p.tok != .key_import {
|
||||||
|
p.fgenln('')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case Token.key_enum:
|
case Token.key_enum:
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -285,7 +289,7 @@ fn (p mut Parser) parse() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) import_statement() {
|
fn (p mut Parser) imports() {
|
||||||
p.check(.key_import)
|
p.check(.key_import)
|
||||||
// `import ()`
|
// `import ()`
|
||||||
if p.tok == .lpar {
|
if p.tok == .lpar {
|
||||||
|
@ -482,7 +486,7 @@ fn (p mut Parser) struct_decl() {
|
||||||
else {
|
else {
|
||||||
// type alias is generated later
|
// type alias is generated later
|
||||||
if !is_c {
|
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;')
|
||||||
p.gen_type('$kind $name {')
|
p.gen_type('$kind $name {')
|
||||||
}
|
}
|
||||||
|
@ -510,9 +514,7 @@ fn (p mut Parser) struct_decl() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Struct `C.Foo` declaration, no body
|
// Struct `C.Foo` declaration, no body
|
||||||
// println('EEEE $is_c $is_struct')
|
|
||||||
if is_c && is_struct && p.tok != .lcbr {
|
if is_c && is_struct && p.tok != .lcbr {
|
||||||
// println('skipping struct header $name')
|
|
||||||
p.table.register_type2(typ)
|
p.table.register_type2(typ)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -522,7 +524,15 @@ fn (p mut Parser) struct_decl() {
|
||||||
mut is_pub := false
|
mut is_pub := false
|
||||||
mut is_mut := false
|
mut is_mut := false
|
||||||
mut names := []string// to avoid dup names TODO alloc perf
|
mut names := []string// to avoid dup names TODO alloc perf
|
||||||
// mut is_mut_mut := false
|
/*
|
||||||
|
mut fmt_max_len := 0
|
||||||
|
for field in typ.fields {
|
||||||
|
if field.name.len > max_len {
|
||||||
|
fmt_max_len = field.name.len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println('fmt max len = $max_len nrfields=$typ.fields.len pass=$p.run')
|
||||||
|
*/
|
||||||
for p.tok != .rcbr {
|
for p.tok != .rcbr {
|
||||||
if p.tok == .key_pub {
|
if p.tok == .key_pub {
|
||||||
if is_pub {
|
if is_pub {
|
||||||
|
@ -592,6 +602,7 @@ fn (p mut Parser) struct_decl() {
|
||||||
}
|
}
|
||||||
if !is_ph && p.first_run() {
|
if !is_ph && p.first_run() {
|
||||||
p.table.register_type2(typ)
|
p.table.register_type2(typ)
|
||||||
|
//println('registering 1 nrfields=$typ.fields.len')
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
if !is_c {
|
if !is_c {
|
||||||
|
@ -619,8 +630,8 @@ fn (p mut Parser) enum_decl(_enum_name string) {
|
||||||
for p.tok == .name {
|
for p.tok == .name {
|
||||||
field := p.check_name()
|
field := p.check_name()
|
||||||
fields << field
|
fields << field
|
||||||
name := '${p.mod}__${enum_name}_$field'
|
|
||||||
p.fgenln('')
|
p.fgenln('')
|
||||||
|
name := '${p.mod}__${enum_name}_$field'
|
||||||
if p.run == .main {
|
if p.run == .main {
|
||||||
p.cgen.consts << '#define $name $val'
|
p.cgen.consts << '#define $name $val'
|
||||||
}
|
}
|
||||||
|
@ -655,7 +666,7 @@ fn (p mut Parser) check_name() string {
|
||||||
|
|
||||||
fn (p mut Parser) check_string() string {
|
fn (p mut Parser) check_string() string {
|
||||||
s := p.lit
|
s := p.lit
|
||||||
p.check(.strtoken)
|
p.check(.str)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,7 +674,7 @@ fn (p &Parser) strtok() string {
|
||||||
if p.tok == .name {
|
if p.tok == .name {
|
||||||
return p.lit
|
return p.lit
|
||||||
}
|
}
|
||||||
if p.tok == .strtoken {
|
if p.tok == .str {
|
||||||
return '"$p.lit"'
|
return '"$p.lit"'
|
||||||
}
|
}
|
||||||
res := p.tok.str()
|
res := p.tok.str()
|
||||||
|
@ -701,6 +712,11 @@ fn (p mut Parser) check(expected Token) {
|
||||||
p.fmt_inc()
|
p.fmt_inc()
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
|
|
||||||
|
if p.scanner.line_comment != '' {
|
||||||
|
//p.fgenln('// ! "$p.scanner.line_comment"')
|
||||||
|
//p.scanner.line_comment = ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) error(s string) {
|
fn (p mut Parser) error(s string) {
|
||||||
|
@ -919,7 +935,7 @@ fn (p &Parser) print_tok() {
|
||||||
println(p.lit)
|
println(p.lit)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if p.tok == .strtoken {
|
if p.tok == .str {
|
||||||
println('"$p.lit"')
|
println('"$p.lit"')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1585,6 +1601,7 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
||||||
if p.tok == .key_type {
|
if p.tok == .key_type {
|
||||||
field_name = 'type'
|
field_name = 'type'
|
||||||
}
|
}
|
||||||
|
p.fgen(field_name)
|
||||||
p.log('dot() field_name=$field_name typ=$str_typ')
|
p.log('dot() field_name=$field_name typ=$str_typ')
|
||||||
//if p.fileis('main.v') {
|
//if p.fileis('main.v') {
|
||||||
//println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}')
|
//println('dot() field_name=$field_name typ=$str_typ prev_tok=${prev_tok.str()}')
|
||||||
|
@ -2120,7 +2137,7 @@ fn (p mut Parser) factor() string {
|
||||||
p.char_expr()
|
p.char_expr()
|
||||||
typ = 'byte'
|
typ = 'byte'
|
||||||
return typ
|
return typ
|
||||||
case Token.strtoken:
|
case Token.str:
|
||||||
p.string_expr()
|
p.string_expr()
|
||||||
typ = 'string'
|
typ = 'string'
|
||||||
return typ
|
return typ
|
||||||
|
@ -2232,11 +2249,11 @@ fn format_str(str string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) string_expr() {
|
fn (p mut Parser) string_expr() {
|
||||||
// println('.strtoken EXPR')
|
// println('.str EXPR')
|
||||||
str := p.lit
|
str := p.lit
|
||||||
p.fgen('\'$str\'')
|
// No ${}, just return a simple string
|
||||||
// No ${}, just return simple string
|
|
||||||
if p.peek() != .dollar {
|
if p.peek() != .dollar {
|
||||||
|
p.fgen('\'$str\'')
|
||||||
// println('before format: "$str"')
|
// println('before format: "$str"')
|
||||||
f := format_str(str)
|
f := format_str(str)
|
||||||
// println('after format: "$str"')
|
// println('after format: "$str"')
|
||||||
|
@ -2252,8 +2269,11 @@ fn (p mut Parser) string_expr() {
|
||||||
// tmp := p.get_tmp()
|
// tmp := p.get_tmp()
|
||||||
mut args := '"'
|
mut args := '"'
|
||||||
mut format := '"'
|
mut format := '"'
|
||||||
for p.tok == .strtoken {
|
p.fgen('\'')
|
||||||
|
mut complex_inter := false // for vfmt
|
||||||
|
for p.tok == .str {
|
||||||
// Add the string between %d's
|
// Add the string between %d's
|
||||||
|
p.fgen(p.lit)
|
||||||
p.lit = p.lit.replace('%', '%%')
|
p.lit = p.lit.replace('%', '%%')
|
||||||
format += format_str(p.lit)
|
format += format_str(p.lit)
|
||||||
p.next()// skip $
|
p.next()// skip $
|
||||||
|
@ -2261,7 +2281,13 @@ fn (p mut Parser) string_expr() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Handle .dollar
|
// Handle .dollar
|
||||||
p.next()
|
p.check(.dollar)
|
||||||
|
// If there's no string after current token, it means we are in
|
||||||
|
// a complex expression (`${...}`)
|
||||||
|
if p.peek() != .str {
|
||||||
|
p.fgen('{')
|
||||||
|
complex_inter = true
|
||||||
|
}
|
||||||
// Get bool expr inside a temp var
|
// Get bool expr inside a temp var
|
||||||
p.cgen.start_tmp()
|
p.cgen.start_tmp()
|
||||||
typ := p.bool_expression()
|
typ := p.bool_expression()
|
||||||
|
@ -2299,6 +2325,10 @@ fn (p mut Parser) string_expr() {
|
||||||
format += f
|
format += f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if complex_inter {
|
||||||
|
p.fgen('}')
|
||||||
|
}
|
||||||
|
p.fgen('\'')
|
||||||
// println("hello %d", num) optimization.
|
// println("hello %d", num) optimization.
|
||||||
if p.cgen.nogen {
|
if p.cgen.nogen {
|
||||||
return
|
return
|
||||||
|
@ -3140,7 +3170,7 @@ else {
|
||||||
fn (p mut Parser) return_st() {
|
fn (p mut Parser) return_st() {
|
||||||
p.cgen.insert_before(p.cur_fn.defer_text)
|
p.cgen.insert_before(p.cur_fn.defer_text)
|
||||||
p.check(.key_return)
|
p.check(.key_return)
|
||||||
|
p.fgen(' ')
|
||||||
fn_returns := p.cur_fn.typ != 'void'
|
fn_returns := p.cur_fn.typ != 'void'
|
||||||
if fn_returns {
|
if fn_returns {
|
||||||
if p.tok == .rcbr {
|
if p.tok == .rcbr {
|
||||||
|
|
|
@ -19,15 +19,15 @@ mut:
|
||||||
debug bool
|
debug bool
|
||||||
line_comment string
|
line_comment string
|
||||||
started bool
|
started bool
|
||||||
is_fmt bool
|
|
||||||
// vfmt fields
|
// vfmt fields
|
||||||
fmt_out strings.Builder
|
fmt_out strings.Builder
|
||||||
fmt_indent int
|
fmt_indent int
|
||||||
fmt_line_empty bool
|
fmt_line_empty bool
|
||||||
|
prev_tok Token
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SINGLE_QUOTE = `\'`
|
SingleQuote = `\'`
|
||||||
//QUOTE = `"`
|
//QUOTE = `"`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -159,9 +159,6 @@ fn (s mut Scanner) skip_whitespace() {
|
||||||
if !(s.text[s.pos] == `\n` && s.pos > 0 && s.text[s.pos-1] == `\r`) {
|
if !(s.text[s.pos] == `\n` && s.pos > 0 && s.text[s.pos-1] == `\r`) {
|
||||||
s.line_nr++
|
s.line_nr++
|
||||||
}
|
}
|
||||||
if s.is_fmt {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
}
|
}
|
||||||
|
@ -179,11 +176,17 @@ fn (s mut Scanner) get_var_name(pos int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CAO stands for Compound Assignment Operators (e.g '+=' )
|
// CAO stands for Compound Assignment Operators (e.g '+=' )
|
||||||
|
/*
|
||||||
fn (s mut Scanner) cao_change(operator string) {
|
fn (s mut Scanner) cao_change(operator string) {
|
||||||
s.text = s.text.substr(0, s.pos - operator.len) + ' = ' + s.get_var_name(s.pos - operator.len) + ' ' + operator + ' ' + s.text.substr(s.pos + 1, s.text.len)
|
s.text = s.text.substr(0, s.pos - operator.len) + ' = ' + s.get_var_name(s.pos - operator.len) + ' ' + operator + ' ' + s.text.substr(s.pos + 1, s.text.len)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fn (s mut Scanner) scan() ScanRes {
|
fn (s mut Scanner) scan() ScanRes {
|
||||||
|
if s.line_comment != '' {
|
||||||
|
//s.fgenln('// LOL "$s.line_comment"')
|
||||||
|
//s.line_comment = ''
|
||||||
|
}
|
||||||
// if s.file_path == 'd.v' {
|
// if s.file_path == 'd.v' {
|
||||||
// println('\nscan()')
|
// println('\nscan()')
|
||||||
// }
|
// }
|
||||||
|
@ -199,19 +202,15 @@ fn (s mut Scanner) scan() ScanRes {
|
||||||
if !s.inside_string {
|
if !s.inside_string {
|
||||||
s.skip_whitespace()
|
s.skip_whitespace()
|
||||||
}
|
}
|
||||||
if s.is_fmt && s.text[s.pos] == `\n` {
|
|
||||||
return scan_res(.nl, '')
|
|
||||||
}
|
|
||||||
// End of $var, start next string
|
// End of $var, start next string
|
||||||
if !s.is_fmt && s.dollar_end {
|
if s.dollar_end {
|
||||||
// fmt.Println("end of $var, get string", s.pos, string(s.text[s.pos]))
|
// fmt.Println("end of $var, get string", s.pos, string(s.text[s.pos]))
|
||||||
if s.text[s.pos] == SINGLE_QUOTE {
|
if s.text[s.pos] == SingleQuote {
|
||||||
// fmt.Println("ENDDD")
|
|
||||||
s.dollar_end = false
|
s.dollar_end = false
|
||||||
return scan_res(.strtoken, '')
|
return scan_res(.str, '')
|
||||||
}
|
}
|
||||||
s.dollar_end = false
|
s.dollar_end = false
|
||||||
return scan_res(.strtoken, s.ident_string())
|
return scan_res(.str, s.ident_string())
|
||||||
}
|
}
|
||||||
s.skip_whitespace()
|
s.skip_whitespace()
|
||||||
// end of file
|
// end of file
|
||||||
|
@ -242,15 +241,15 @@ fn (s mut Scanner) scan() ScanRes {
|
||||||
// at the next ', skip it
|
// at the next ', skip it
|
||||||
if s.inside_string {
|
if s.inside_string {
|
||||||
// println('is_letter inside string! nextc=${nextc.str()}')
|
// println('is_letter inside string! nextc=${nextc.str()}')
|
||||||
if next_char == SINGLE_QUOTE {
|
if next_char == SingleQuote {
|
||||||
// println('var is last before QUOTE')
|
// println('var is last before QUOTE')
|
||||||
s.pos++
|
s.pos++
|
||||||
s.dollar_start = false
|
s.dollar_start = false
|
||||||
s.inside_string = false
|
s.inside_string = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.dollar_start && next_char != `.` {
|
if s.dollar_start && next_char != `.` {//&& next_char != `(` {
|
||||||
// println('INSIDE .strtoken .dollar var=$name')
|
// println('INSIDE .str .dollar var=$name')
|
||||||
s.dollar_end = true
|
s.dollar_end = true
|
||||||
s.dollar_start = false
|
s.dollar_start = false
|
||||||
}
|
}
|
||||||
|
@ -261,7 +260,7 @@ fn (s mut Scanner) scan() ScanRes {
|
||||||
}
|
}
|
||||||
return scan_res(.name, name)
|
return scan_res(.name, name)
|
||||||
}
|
}
|
||||||
// number, `.123`
|
// `123`, `.123`
|
||||||
else if c.is_digit() || c == `.` && nextc.is_digit() {
|
else if c.is_digit() || c == `.` && nextc.is_digit() {
|
||||||
num := s.ident_number()
|
num := s.ident_number()
|
||||||
return scan_res(.integer, num)
|
return scan_res(.integer, num)
|
||||||
|
@ -308,11 +307,11 @@ fn (s mut Scanner) scan() ScanRes {
|
||||||
return scan_res(.mod, '')
|
return scan_res(.mod, '')
|
||||||
case `?`:
|
case `?`:
|
||||||
return scan_res(.question, '')
|
return scan_res(.question, '')
|
||||||
case SINGLE_QUOTE:
|
case SingleQuote:
|
||||||
return scan_res(.strtoken, s.ident_string())
|
return scan_res(.str, s.ident_string())
|
||||||
// TODO allow double quotes
|
// TODO allow double quotes
|
||||||
// case QUOTE:
|
// case QUOTE:
|
||||||
// return scan_res(.strtoken, s.ident_string())
|
// return scan_res(.str, s.ident_string())
|
||||||
case `\``:
|
case `\``:
|
||||||
return scan_res(.chartoken, s.ident_char())
|
return scan_res(.chartoken, s.ident_char())
|
||||||
case `(`:
|
case `(`:
|
||||||
|
@ -337,11 +336,11 @@ fn (s mut Scanner) scan() ScanRes {
|
||||||
if s.inside_string {
|
if s.inside_string {
|
||||||
s.pos++
|
s.pos++
|
||||||
// TODO UN.neEDED?
|
// TODO UN.neEDED?
|
||||||
if s.text[s.pos] == SINGLE_QUOTE {
|
if s.text[s.pos] == SingleQuote {
|
||||||
s.inside_string = false
|
s.inside_string = false
|
||||||
return scan_res(.strtoken, '')
|
return scan_res(.str, '')
|
||||||
}
|
}
|
||||||
return scan_res(.strtoken, s.ident_string())
|
return scan_res(.str, s.ident_string())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return scan_res(.rcbr, '')
|
return scan_res(.rcbr, '')
|
||||||
|
@ -388,10 +387,6 @@ fn (s mut Scanner) scan() ScanRes {
|
||||||
}
|
}
|
||||||
s.line_nr++
|
s.line_nr++
|
||||||
hash := s.text.substr(start, s.pos)
|
hash := s.text.substr(start, s.pos)
|
||||||
if s.is_fmt {
|
|
||||||
// fmt needs NL after #
|
|
||||||
s.pos--
|
|
||||||
}
|
|
||||||
return scan_res(.hash, hash.trim_space())
|
return scan_res(.hash, hash.trim_space())
|
||||||
case `>`:
|
case `>`:
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
|
@ -471,16 +466,9 @@ fn (s mut Scanner) scan() ScanRes {
|
||||||
s.line_nr++
|
s.line_nr++
|
||||||
s.line_comment = s.text.substr(start + 1, s.pos)
|
s.line_comment = s.text.substr(start + 1, s.pos)
|
||||||
s.line_comment = s.line_comment.trim_space()
|
s.line_comment = s.line_comment.trim_space()
|
||||||
s.fgenln('// $s.line_comment')
|
s.fgenln('// ${s.prev_tok.str()} "$s.line_comment"')
|
||||||
if s.is_fmt {
|
// Skip the comment (return the next token)
|
||||||
// fmt needs NL after comment
|
return s.scan()
|
||||||
s.pos--
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Skip comment
|
|
||||||
return s.scan()
|
|
||||||
}
|
|
||||||
return scan_res(.line_com, s.line_comment)
|
|
||||||
}
|
}
|
||||||
// Multiline comments
|
// Multiline comments
|
||||||
if nextc == `*` {
|
if nextc == `*` {
|
||||||
|
@ -509,9 +497,6 @@ fn (s mut Scanner) scan() ScanRes {
|
||||||
end := s.pos + 1
|
end := s.pos + 1
|
||||||
comm := s.text.substr(start, end)
|
comm := s.text.substr(start, end)
|
||||||
s.fgenln(comm)
|
s.fgenln(comm)
|
||||||
if s.is_fmt {
|
|
||||||
return scan_res(.mline_com, comm)
|
|
||||||
}
|
|
||||||
// Skip if not in fmt mode
|
// Skip if not in fmt mode
|
||||||
return s.scan()
|
return s.scan()
|
||||||
}
|
}
|
||||||
|
@ -564,7 +549,7 @@ fn (s mut Scanner) ident_string() string {
|
||||||
}
|
}
|
||||||
prevc := s.text[s.pos - 1]
|
prevc := s.text[s.pos - 1]
|
||||||
// end of string
|
// end of string
|
||||||
if c == SINGLE_QUOTE && (prevc != slash || (prevc == slash && s.text[s.pos - 2] == slash)) {
|
if c == SingleQuote && (prevc != slash || (prevc == slash && s.text[s.pos - 2] == slash)) {
|
||||||
// handle '123\\' slash at the end
|
// handle '123\\' slash at the end
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -581,17 +566,15 @@ fn (s mut Scanner) ident_string() string {
|
||||||
s.error('0 character in a string literal')
|
s.error('0 character in a string literal')
|
||||||
}
|
}
|
||||||
// ${var}
|
// ${var}
|
||||||
if !s.is_fmt && c == `{` && prevc == `$` {
|
if c == `{` && prevc == `$` {
|
||||||
s.inside_string = true
|
s.inside_string = true
|
||||||
// fmt.Println("breaking out of is()")
|
|
||||||
// so that s.pos points to $ at the next step
|
// so that s.pos points to $ at the next step
|
||||||
s.pos -= 2
|
s.pos -= 2
|
||||||
// fmt.Println("break pos=", s.pos, "c=", string(s.text[s.pos]), "d=", s.text[s.pos])
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// $var
|
// $var
|
||||||
// if !s.is_fmt && c != `{` && c != ` ` && ! (c >= `0` && c <= `9`) && prevc == `$` {
|
// if !s.is_fmt && c != `{` && c != ` ` && ! (c >= `0` && c <= `9`) && prevc == `$` {
|
||||||
if !s.is_fmt && (c.is_letter() || c == `_`) && prevc == `$` {
|
if (c.is_letter() || c == `_`) && prevc == `$` {
|
||||||
s.inside_string = true
|
s.inside_string = true
|
||||||
s.dollar_start = true
|
s.dollar_start = true
|
||||||
// println('setting s.dollar=true pos=$s.pos')
|
// println('setting s.dollar=true pos=$s.pos')
|
||||||
|
@ -600,7 +583,7 @@ fn (s mut Scanner) ident_string() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut lit := ''
|
mut lit := ''
|
||||||
if s.text[start] == SINGLE_QUOTE {
|
if s.text[start] == SingleQuote {
|
||||||
start++
|
start++
|
||||||
}
|
}
|
||||||
mut end := s.pos
|
mut end := s.pos
|
||||||
|
@ -685,7 +668,7 @@ fn (s mut Scanner) peek() Token {
|
||||||
fn (s mut Scanner) debug_tokens() {
|
fn (s mut Scanner) debug_tokens() {
|
||||||
s.pos = 0
|
s.pos = 0
|
||||||
fname := s.file_path.all_after('/')
|
fname := s.file_path.all_after('/')
|
||||||
println('\n===DEBUG TOKENS $fname ============')
|
println('\n===DEBUG TOKENS $fname===')
|
||||||
// allToks := ''
|
// allToks := ''
|
||||||
s.debug = true
|
s.debug = true
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -6,20 +6,21 @@ module main
|
||||||
|
|
||||||
enum Token {
|
enum Token {
|
||||||
eof
|
eof
|
||||||
name
|
name // user
|
||||||
integer
|
integer // 123
|
||||||
strtoken
|
str // 'foo'
|
||||||
chartoken
|
str_inter // 'name=$user.name'
|
||||||
|
chartoken // `A`
|
||||||
plus
|
plus
|
||||||
minus
|
minus
|
||||||
mul
|
mul
|
||||||
div
|
div
|
||||||
mod
|
mod
|
||||||
xor
|
xor // ^
|
||||||
pipe
|
pipe // |
|
||||||
inc
|
inc // ++
|
||||||
dec
|
dec // --
|
||||||
and
|
and // &&
|
||||||
logical_or
|
logical_or
|
||||||
not
|
not
|
||||||
bit_not
|
bit_not
|
||||||
|
@ -61,8 +62,8 @@ enum Token {
|
||||||
ge
|
ge
|
||||||
le
|
le
|
||||||
// comments
|
// comments
|
||||||
line_com
|
//line_com
|
||||||
mline_com
|
//mline_com
|
||||||
nl
|
nl
|
||||||
dot
|
dot
|
||||||
dotdot
|
dotdot
|
||||||
|
@ -127,7 +128,7 @@ fn build_token_str() []string {
|
||||||
s[Token.eof] = '.eof'
|
s[Token.eof] = '.eof'
|
||||||
s[Token.name] = '.name'
|
s[Token.name] = '.name'
|
||||||
s[Token.integer] = '.integer'
|
s[Token.integer] = '.integer'
|
||||||
s[Token.strtoken] = 'STR'
|
s[Token.str] = 'STR'
|
||||||
s[Token.chartoken] = '.chartoken'
|
s[Token.chartoken] = '.chartoken'
|
||||||
s[Token.plus] = '+'
|
s[Token.plus] = '+'
|
||||||
s[Token.minus] = '-'
|
s[Token.minus] = '-'
|
||||||
|
@ -177,7 +178,7 @@ fn build_token_str() []string {
|
||||||
s[Token.question] = '?'
|
s[Token.question] = '?'
|
||||||
s[Token.left_shift] = '<<'
|
s[Token.left_shift] = '<<'
|
||||||
s[Token.righ_shift] = '>>'
|
s[Token.righ_shift] = '>>'
|
||||||
s[Token.line_com] = '//'
|
//s[Token.line_com] = '//'
|
||||||
s[Token.nl] = 'NLL'
|
s[Token.nl] = 'NLL'
|
||||||
s[Token.dollar] = '$'
|
s[Token.dollar] = '$'
|
||||||
s[Token.key_assert] = 'assert'
|
s[Token.key_assert] = 'assert'
|
||||||
|
|
|
@ -27,4 +27,4 @@ fn standing_line(x,y,size int, ch string) {
|
||||||
print(term.bold(term.yellow(ch)))
|
print(term.bold(term.yellow(ch)))
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,3 +299,22 @@ fn test_reverse() {
|
||||||
t := ''
|
t := ''
|
||||||
assert t.reverse() == t
|
assert t.reverse() == t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
bar int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (f Foo) baz() string {
|
||||||
|
return 'baz'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_interpolation() {
|
||||||
|
num := 7
|
||||||
|
mut s := 'number=$num'
|
||||||
|
assert s == 'number=7'
|
||||||
|
foo := Foo{}
|
||||||
|
s = 'baz=${foo.baz()}'
|
||||||
|
assert s == 'baz=baz'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -505,4 +505,4 @@ pub fn (c Complex) acsch() Complex {
|
||||||
// Complex Equals
|
// Complex Equals
|
||||||
pub fn (c1 Complex) equals(c2 Complex) bool {
|
pub fn (c1 Complex) equals(c2 Complex) bool {
|
||||||
return (c1.re == c2.re) && (c1.im == c2.im)
|
return (c1.re == c2.re) && (c1.im == c2.im)
|
||||||
}
|
}
|
||||||
|
|
|
@ -771,4 +771,4 @@ fn test_complex_acsch() {
|
||||||
result = c1.acsch()
|
result = c1.acsch()
|
||||||
// Some issue with precision comparison in f64 using == operator hence serializing to string
|
// Some issue with precision comparison in f64 using == operator hence serializing to string
|
||||||
assert result.str().eq(c2.str())
|
assert result.str().eq(c2.str())
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,4 +145,4 @@ fn block(dig &Digest, p []byte) {
|
||||||
|
|
||||||
pub fn (d &Digest) size() int { return Size }
|
pub fn (d &Digest) size() int { return Size }
|
||||||
|
|
||||||
pub fn (d &Digest) block_size() int { return BlockSize }
|
pub fn (d &Digest) block_size() int { return BlockSize }
|
||||||
|
|
|
@ -150,4 +150,4 @@ fn block(dig &Digest, p []byte) {
|
||||||
|
|
||||||
pub fn (d &Digest) size() int { return Size }
|
pub fn (d &Digest) size() int { return Size }
|
||||||
|
|
||||||
pub fn (d &Digest) block_size() int { return BlockSize }
|
pub fn (d &Digest) block_size() int { return BlockSize }
|
||||||
|
|
|
@ -90,4 +90,4 @@ pub fn big_endian_put_u64(b []byte, v u64) {
|
||||||
b[5] = byte(v >> u64(16))
|
b[5] = byte(v >> u64(16))
|
||||||
b[6] = byte(v >> u64(8))
|
b[6] = byte(v >> u64(8))
|
||||||
b[7] = byte(v)
|
b[7] = byte(v)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,4 @@ fn test_hash_crc32() {
|
||||||
c := crc32.new(crc32.IEEE)
|
c := crc32.new(crc32.IEEE)
|
||||||
assert c.checksum('testing crc32 again') == u32(1420327025)
|
assert c.checksum('testing crc32 again') == u32(1420327025)
|
||||||
assert c.checksum('testing crc32 again').hex() == '0x54a87871'
|
assert c.checksum('testing crc32 again').hex() == '0x54a87871'
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,4 +50,4 @@ pub fn (l Log) debug(s string){
|
||||||
f := term.blue('D')
|
f := term.blue('D')
|
||||||
println('[$f]$s')
|
println('[$f]$s')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,4 +44,4 @@ pub fn rotate_left_64(x u64, k int) u64 {
|
||||||
n := u64(64)
|
n := u64(64)
|
||||||
s := u64(k) & (n - u64(1))
|
s := u64(k) & (n - u64(1))
|
||||||
return u64(u64(x<<s) | u64(x>>(n-s)))
|
return u64(u64(x<<s) | u64(x>>(n-s)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,4 +138,4 @@ fn test_gcd_and_reduce(){
|
||||||
mut f := fractions.fraction(3, 9)
|
mut f := fractions.fraction(3, 9)
|
||||||
assert f.gcd() == 3
|
assert f.gcd() == 3
|
||||||
assert f.reduce().equals(fractions.fraction(1, 3))
|
assert f.reduce().equals(fractions.fraction(1, 3))
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,4 +128,4 @@ pub fn white(msg string) string {
|
||||||
|
|
||||||
pub fn yellow(msg string) string {
|
pub fn yellow(msg string) string {
|
||||||
return format(msg, '33', '39')
|
return format(msg, '33', '39')
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,4 +107,4 @@ pub fn show_cursor()
|
||||||
pub fn hide_cursor()
|
pub fn hide_cursor()
|
||||||
{
|
{
|
||||||
print('\x1b[?25l')
|
print('\x1b[?25l')
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue