cgen: use *char in all functions with *char args to avoid warnings
parent
35f927e64e
commit
48c05b5a45
|
@ -4,7 +4,7 @@ I tried making the code of the compiler and vlib as simple and readable as possi
|
||||||
|
|
||||||
The compiler itself is located in `compiler/`
|
The compiler itself is located in `compiler/`
|
||||||
|
|
||||||
It has only 8 files (soon to be 7):
|
The main files are:
|
||||||
|
|
||||||
1. `main.v` The entry point.
|
1. `main.v` The entry point.
|
||||||
- V figures out the build mode.
|
- V figures out the build mode.
|
||||||
|
@ -19,7 +19,7 @@ It has only 8 files (soon to be 7):
|
||||||
In V, objects can be used before declaration, so there are 2 passes. During the first pass, it only looks at declarations and skips function bodies. It memorizes all function signatures, types, consts, etc. During the second pass it looks at function bodies and generates C (e.g. `cgen('if ($expr) {'`) or machine code (e.g. `gen.mov(EDI, 1)`).
|
In V, objects can be used before declaration, so there are 2 passes. During the first pass, it only looks at declarations and skips function bodies. It memorizes all function signatures, types, consts, etc. During the second pass it looks at function bodies and generates C (e.g. `cgen('if ($expr) {'`) or machine code (e.g. `gen.mov(EDI, 1)`).
|
||||||
|
|
||||||
The formatter is embedded in the parser. Correctly formatted tokens are emitted as they are parsed. This allowed to simplify the compiler and avoid duplication, but slowed it down a bit. In the future this will be fixed with build flags and separate binaries for C generation, machine code generation, and formatting. This way there will be no unnecessary branching and function calls.
|
The formatter is embedded in the parser. Correctly formatted tokens are emitted as they are parsed. This allowed to simplify the compiler and avoid duplication, but slowed it down a bit. In the future this will be fixed with build flags and separate binaries for C generation, machine code generation, and formatting. This way there will be no unnecessary branching and function calls.
|
||||||
|
|
||||||
3. `scanner.v` The scanner's job is to parse a list of characters and convert them to tokens. It also takes care of string interpolation, which is a mess at the moment.
|
3. `scanner.v` The scanner's job is to parse a list of characters and convert them to tokens. It also takes care of string interpolation, which is a mess at the moment.
|
||||||
|
|
||||||
4. `token.v` This is simply a list of all tokens, their string values, and a couple of helper functions.
|
4. `token.v` This is simply a list of all tokens, their string values, and a couple of helper functions.
|
||||||
|
|
|
@ -746,14 +746,17 @@ fn (p mut Parser) fn_args(f mut Fn) {
|
||||||
|
|
||||||
// foo *(1, 2, 3, mut bar)*
|
// foo *(1, 2, 3, mut bar)*
|
||||||
fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
fn (p mut Parser) fn_call_args(f mut Fn) &Fn {
|
||||||
// p.gen('(')
|
|
||||||
// println('fn_call_args() name=$f.name args.len=$f.args.len')
|
// println('fn_call_args() name=$f.name args.len=$f.args.len')
|
||||||
// C func. # of args is not known
|
// C func. # of args is not known
|
||||||
// if f.name.starts_with('c_') {
|
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
if f.is_c {
|
if f.is_c {
|
||||||
for p.tok != .rpar {
|
for p.tok != .rpar {
|
||||||
p.bool_expression()
|
ph := p.cgen.add_placeholder()
|
||||||
|
typ := p.bool_expression()
|
||||||
|
// Cast V byteptr to C char* (byte is unsigned in V, that led to C warnings)
|
||||||
|
if typ == 'byte*' {
|
||||||
|
p.cgen.set_placeholder(ph, '(char*)')
|
||||||
|
}
|
||||||
if p.tok == .comma {
|
if p.tok == .comma {
|
||||||
p.gen(', ')
|
p.gen(', ')
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
|
|
|
@ -3171,6 +3171,7 @@ fn (p mut Parser) switch_statement() {
|
||||||
}
|
}
|
||||||
p.cgen.start_tmp()
|
p.cgen.start_tmp()
|
||||||
typ := p.bool_expression()
|
typ := p.bool_expression()
|
||||||
|
is_str := typ == 'string'
|
||||||
expr := p.cgen.end_tmp()
|
expr := p.cgen.end_tmp()
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
mut i := 0
|
mut i := 0
|
||||||
|
@ -3198,13 +3199,16 @@ fn (p mut Parser) switch_statement() {
|
||||||
mut got_comma := false
|
mut got_comma := false
|
||||||
for {
|
for {
|
||||||
if got_comma {
|
if got_comma {
|
||||||
p.gen(') || ')
|
if is_str {
|
||||||
|
p.gen(')')
|
||||||
|
}
|
||||||
|
p.gen(' || ')
|
||||||
}
|
}
|
||||||
if typ == 'string' {
|
if typ == 'string' {
|
||||||
p.gen('string_eq($expr, ')
|
p.gen('string_eq($expr, ')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.gen('($expr == ')
|
p.gen('$expr == ')
|
||||||
}
|
}
|
||||||
if p.tok == .key_case || p.tok == .key_default {
|
if p.tok == .key_case || p.tok == .key_default {
|
||||||
p.check(p.tok)
|
p.check(p.tok)
|
||||||
|
@ -3222,7 +3226,10 @@ fn (p mut Parser) switch_statement() {
|
||||||
else {
|
else {
|
||||||
p.check(.arrow)
|
p.check(.arrow)
|
||||||
}
|
}
|
||||||
p.gen(')) {')
|
if is_str {
|
||||||
|
p.gen(')')
|
||||||
|
}
|
||||||
|
p.gen(') {')
|
||||||
p.genln('/* case */')
|
p.genln('/* case */')
|
||||||
p.statements()
|
p.statements()
|
||||||
all_cases_return = all_cases_return && p.returns
|
all_cases_return = all_cases_return && p.returns
|
||||||
|
|
36
vlib/os/os.v
36
vlib/os/os.v
|
@ -77,12 +77,7 @@ fn parse_windows_cmd_line(cmd byteptr) []string {
|
||||||
// read_file reads the file in `path` and returns the contents.
|
// read_file reads the file in `path` and returns the contents.
|
||||||
pub fn read_file(path string) ?string {
|
pub fn read_file(path string) ?string {
|
||||||
mode := 'rb'
|
mode := 'rb'
|
||||||
mut fp := &C.FILE{!}
|
mut fp := vfopen(path, mode)
|
||||||
$if windows {
|
|
||||||
fp = C._wfopen(path.to_wide(), mode.to_wide())
|
|
||||||
} $else {
|
|
||||||
fp = C.fopen(path.str, mode.str)
|
|
||||||
}
|
|
||||||
if isnil(fp) {
|
if isnil(fp) {
|
||||||
return error('failed to open file "$path"')
|
return error('failed to open file "$path"')
|
||||||
}
|
}
|
||||||
|
@ -103,7 +98,7 @@ pub fn file_size(path string) int {
|
||||||
$if windows {
|
$if windows {
|
||||||
C._wstat(path.to_wide(), &s)
|
C._wstat(path.to_wide(), &s)
|
||||||
} $else {
|
} $else {
|
||||||
C.stat(path.str, &s)
|
C.stat(*char(path.str), &s)
|
||||||
}
|
}
|
||||||
return s.st_size
|
return s.st_size
|
||||||
}
|
}
|
||||||
|
@ -112,10 +107,18 @@ pub fn mv(old, new string) {
|
||||||
$if windows {
|
$if windows {
|
||||||
C._wrename(old.to_wide(), new.to_wide())
|
C._wrename(old.to_wide(), new.to_wide())
|
||||||
} $else {
|
} $else {
|
||||||
C.rename(old.str, new.str)
|
C.rename(*char(old.str), *char(new.str))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vfopen(path, mode string) *C.FILE {
|
||||||
|
$if windows {
|
||||||
|
return C._wfopen(path.to_wide(), mode.to_wide())
|
||||||
|
} $else {
|
||||||
|
return C.fopen(*char(path.str), *char(mode.str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// read_lines reads the file in `path` into an array of lines.
|
// read_lines reads the file in `path` into an array of lines.
|
||||||
// TODO return `?[]string` TODO implement `?[]` support
|
// TODO return `?[]string` TODO implement `?[]` support
|
||||||
pub fn read_lines(path string) []string {
|
pub fn read_lines(path string) []string {
|
||||||
|
@ -124,12 +127,7 @@ pub fn read_lines(path string) []string {
|
||||||
mut buf := malloc(buf_len)
|
mut buf := malloc(buf_len)
|
||||||
|
|
||||||
mode := 'rb'
|
mode := 'rb'
|
||||||
mut fp := &C.FILE{!}
|
mut fp := vfopen(path, mode)
|
||||||
$if windows {
|
|
||||||
fp = C._wfopen(path.to_wide(), mode.to_wide())
|
|
||||||
} $else {
|
|
||||||
fp = C.fopen(path.str, mode.str)
|
|
||||||
}
|
|
||||||
if isnil(fp) {
|
if isnil(fp) {
|
||||||
// TODO
|
// TODO
|
||||||
// return error('failed to open file "$path"')
|
// return error('failed to open file "$path"')
|
||||||
|
@ -183,7 +181,7 @@ pub fn open(path string) ?File {
|
||||||
} $else {
|
} $else {
|
||||||
cpath := path.str
|
cpath := path.str
|
||||||
file = File {
|
file = File {
|
||||||
cfile: C.fopen(cpath, 'rb')
|
cfile: C.fopen(*char(cpath), 'rb')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isnil(file.cfile) {
|
if isnil(file.cfile) {
|
||||||
|
@ -204,7 +202,7 @@ pub fn create(path string) ?File {
|
||||||
} $else {
|
} $else {
|
||||||
cpath := path.str
|
cpath := path.str
|
||||||
file = File {
|
file = File {
|
||||||
cfile: C.fopen(cpath, 'wb')
|
cfile: C.fopen(*char(cpath), 'wb')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isnil(file.cfile) {
|
if isnil(file.cfile) {
|
||||||
|
@ -224,7 +222,7 @@ pub fn open_append(path string) ?File {
|
||||||
} $else {
|
} $else {
|
||||||
cpath := path.str
|
cpath := path.str
|
||||||
file = File {
|
file = File {
|
||||||
cfile: C.fopen(cpath, 'ab')
|
cfile: C.fopen(*char(cpath), 'ab')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isnil(file.cfile) {
|
if isnil(file.cfile) {
|
||||||
|
@ -306,7 +304,7 @@ pub fn exec(cmd string) ?Result {
|
||||||
}
|
}
|
||||||
buf := [1000]byte
|
buf := [1000]byte
|
||||||
mut res := ''
|
mut res := ''
|
||||||
for C.fgets(buf, 1000, f) != 0 {
|
for C.fgets(*char(buf), 1000, f) != 0 {
|
||||||
res += tos(buf, vstrlen(buf))
|
res += tos(buf, vstrlen(buf))
|
||||||
}
|
}
|
||||||
res = res.trim_space()
|
res = res.trim_space()
|
||||||
|
@ -342,7 +340,7 @@ pub fn getenv(key string) string {
|
||||||
}
|
}
|
||||||
return string_from_wide(s)
|
return string_from_wide(s)
|
||||||
} $else {
|
} $else {
|
||||||
s := C.getenv(key.str)
|
s := *byte(C.getenv(key.str))
|
||||||
if isnil(s) {
|
if isnil(s) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue