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