cgen: use *char in all functions with *char args to avoid warnings

pull/1996/head^2
Alexander Medvednikov 2019-09-15 15:57:17 +03:00
parent 35f927e64e
commit 48c05b5a45
4 changed files with 35 additions and 27 deletions

View File

@ -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/`
It has only 8 files (soon to be 7):
The main files are:
1. `main.v` The entry point.
- 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)`).
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.
4. `token.v` This is simply a list of all tokens, their string values, and a couple of helper functions.

View File

@ -746,14 +746,17 @@ fn (p mut Parser) fn_args(f mut Fn) {
// foo *(1, 2, 3, mut bar)*
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')
// C func. # of args is not known
// if f.name.starts_with('c_') {
p.check(.lpar)
if f.is_c {
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 {
p.gen(', ')
p.check(.comma)

View File

@ -3171,6 +3171,7 @@ fn (p mut Parser) switch_statement() {
}
p.cgen.start_tmp()
typ := p.bool_expression()
is_str := typ == 'string'
expr := p.cgen.end_tmp()
p.check(.lcbr)
mut i := 0
@ -3198,13 +3199,16 @@ fn (p mut Parser) switch_statement() {
mut got_comma := false
for {
if got_comma {
p.gen(') || ')
if is_str {
p.gen(')')
}
p.gen(' || ')
}
if typ == 'string' {
p.gen('string_eq($expr, ')
}
else {
p.gen('($expr == ')
p.gen('$expr == ')
}
if p.tok == .key_case || p.tok == .key_default {
p.check(p.tok)
@ -3222,7 +3226,10 @@ fn (p mut Parser) switch_statement() {
else {
p.check(.arrow)
}
p.gen(')) {')
if is_str {
p.gen(')')
}
p.gen(') {')
p.genln('/* case */')
p.statements()
all_cases_return = all_cases_return && p.returns

View File

@ -77,12 +77,7 @@ fn parse_windows_cmd_line(cmd byteptr) []string {
// read_file reads the file in `path` and returns the contents.
pub fn read_file(path string) ?string {
mode := 'rb'
mut fp := &C.FILE{!}
$if windows {
fp = C._wfopen(path.to_wide(), mode.to_wide())
} $else {
fp = C.fopen(path.str, mode.str)
}
mut fp := vfopen(path, mode)
if isnil(fp) {
return error('failed to open file "$path"')
}
@ -103,7 +98,7 @@ pub fn file_size(path string) int {
$if windows {
C._wstat(path.to_wide(), &s)
} $else {
C.stat(path.str, &s)
C.stat(*char(path.str), &s)
}
return s.st_size
}
@ -112,10 +107,18 @@ pub fn mv(old, new string) {
$if windows {
C._wrename(old.to_wide(), new.to_wide())
} $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.
// TODO return `?[]string` TODO implement `?[]` support
pub fn read_lines(path string) []string {
@ -124,12 +127,7 @@ pub fn read_lines(path string) []string {
mut buf := malloc(buf_len)
mode := 'rb'
mut fp := &C.FILE{!}
$if windows {
fp = C._wfopen(path.to_wide(), mode.to_wide())
} $else {
fp = C.fopen(path.str, mode.str)
}
mut fp := vfopen(path, mode)
if isnil(fp) {
// TODO
// return error('failed to open file "$path"')
@ -183,7 +181,7 @@ pub fn open(path string) ?File {
} $else {
cpath := path.str
file = File {
cfile: C.fopen(cpath, 'rb')
cfile: C.fopen(*char(cpath), 'rb')
}
}
if isnil(file.cfile) {
@ -204,7 +202,7 @@ pub fn create(path string) ?File {
} $else {
cpath := path.str
file = File {
cfile: C.fopen(cpath, 'wb')
cfile: C.fopen(*char(cpath), 'wb')
}
}
if isnil(file.cfile) {
@ -224,7 +222,7 @@ pub fn open_append(path string) ?File {
} $else {
cpath := path.str
file = File {
cfile: C.fopen(cpath, 'ab')
cfile: C.fopen(*char(cpath), 'ab')
}
}
if isnil(file.cfile) {
@ -306,7 +304,7 @@ pub fn exec(cmd string) ?Result {
}
buf := [1000]byte
mut res := ''
for C.fgets(buf, 1000, f) != 0 {
for C.fgets(*char(buf), 1000, f) != 0 {
res += tos(buf, vstrlen(buf))
}
res = res.trim_space()
@ -342,7 +340,7 @@ pub fn getenv(key string) string {
}
return string_from_wide(s)
} $else {
s := C.getenv(key.str)
s := *byte(C.getenv(key.str))
if isnil(s) {
return ''
}