1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: skip $if os {} block

This commit is contained in:
Alexander Medvednikov 2020-03-27 14:44:30 +01:00
parent 3a691dcc6d
commit 1a751208ca
5 changed files with 139 additions and 38 deletions

View File

@ -36,7 +36,7 @@ pub fn new_builder(pref &pref.Preferences) Builder {
pub fn (b mut Builder) gen_c(v_files []string) string {
t0 := time.ticks()
b.parsed_files = parser.parse_files(v_files, b.table)
b.parsed_files = parser.parse_files(v_files, b.table, b.pref)
b.parse_imports()
t1 := time.ticks()
parse_time := t1 - t0
@ -71,7 +71,7 @@ pub fn (b mut Builder) build_c(v_files []string, out_file string) {
pub fn (b mut Builder) build_x64(v_files []string, out_file string) {
t0 := time.ticks()
b.parsed_files = parser.parse_files(v_files, b.table)
b.parsed_files = parser.parse_files(v_files, b.table, b.pref)
b.parse_imports()
t1 := time.ticks()
parse_time := t1 - t0
@ -109,7 +109,7 @@ pub fn (b mut Builder) parse_imports() {
panic('cannot import module "$mod" (no .v files in "$import_path")')
}
// Add all imports referenced by these libs
parsed_files := parser.parse_files(v_files, b.table)
parsed_files := parser.parse_files(v_files, b.table, b.pref)
for file in parsed_files {
if file.mod.name != mod {
// v.parsers[pidx].error_with_token_index('bad module definition: ${v.parsers[pidx].file_path} imports module "$mod" but $file is defined as module `$p_mod`', 1

View File

@ -45,7 +45,7 @@ pub fn doc(mod string, table &table.Table) string {
if file.ends_with('_test.v') || file.ends_with('_windows.v') || file.ends_with('_macos.v') {
continue
}
file_ast := parser.parse_file(os.join_path(path,file), table, .skip_comments)
file_ast := parser.parse_file(os.join_path(path,file), table, .skip_comments, &pref.Preferences{})
d.stmts << file_ast.stmts
}
if d.stmts.len == 0 {

View File

@ -295,28 +295,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.const_decl(it)
}
ast.CompIf {
ifdef := comp_if_to_ifdef(it.val)
if it.is_not {
g.writeln('\n#ifndef ' + ifdef)
g.writeln('// #if not $it.val')
}
else {
g.writeln('\n#ifdef ' + ifdef)
g.writeln('// #if $it.val')
}
// NOTE: g.defer_ifdef is needed for defers called witin an ifdef
// in v1 this code would be completely excluded
g.defer_ifdef = if it.is_not { '#ifndef ' + ifdef } else { '#ifdef ' + ifdef }
// println('comp if stmts $g.file.path:$it.pos.line_nr')
g.stmts(it.stmts)
g.defer_ifdef = ''
if it.has_else {
g.writeln('#else')
g.defer_ifdef = if it.is_not { '#ifdef ' + ifdef } else { '#ifndef ' + ifdef }
g.stmts(it.else_stmts)
g.defer_ifdef = ''
}
g.writeln('#endif')
g.comp_if(it)
}
ast.DeferStmt {
mut defer_stmt := *it
@ -2494,3 +2473,28 @@ pub fn (g mut Gen) write_tests_main() {
fn (g &Gen) is_importing_os() bool {
return 'os' in g.table.imports
}
fn (g mut Gen) comp_if(it ast.CompIf) {
ifdef := comp_if_to_ifdef(it.val)
if it.is_not {
g.writeln('\n#ifndef ' + ifdef)
g.writeln('// #if not $it.val')
}
else {
g.writeln('\n#ifdef ' + ifdef)
g.writeln('// #if $it.val')
}
// NOTE: g.defer_ifdef is needed for defers called witin an ifdef
// in v1 this code would be completely excluded
g.defer_ifdef = if it.is_not { '#ifndef ' + ifdef } else { '#ifdef ' + ifdef }
// println('comp if stmts $g.file.path:$it.pos.line_nr')
g.stmts(it.stmts)
g.defer_ifdef = ''
if it.has_else {
g.writeln('#else')
g.defer_ifdef = if it.is_not { '#ifdef ' + ifdef } else { '#ifndef ' + ifdef }
g.stmts(it.else_stmts)
g.defer_ifdef = ''
}
g.writeln('#endif')
}

View File

@ -2,9 +2,15 @@ module parser
import (
v.ast
v.pref
)
pub fn (p mut Parser) comp_if() ast.CompIf {
const (
supported_platforms = ['windows', 'mac', 'macos', 'linux', 'freebsd', 'openbsd', 'netbsd',
'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
)
fn (p mut Parser) comp_if() ast.CompIf {
pos := p.tok.position()
p.next()
p.check(.key_if)
@ -13,14 +19,51 @@ pub fn (p mut Parser) comp_if() ast.CompIf {
p.next()
}
val := p.check_name()
mut stmts := []ast.Stmt
mut skip_os := false
if val in supported_platforms {
os := os_from_string(val)
// `$if os {` for a different target, skip everything inside
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns
// on non-Windows systems)
if ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) && !p.pref.output_cross_c {
skip_os = true
p.check(.lcbr)
p.warn('SKIPPING $val os=$os p.pref.os=$p.pref.os')
mut stack := 1
for {
if p.tok.kind == .key_return {
p.returns = true
}
if p.tok.kind == .lcbr {
stack++
}
else if p.tok.kind == .rcbr {
stack--
}
if p.tok.kind == .eof {
break
}
if stack <= 0 && p.tok.kind == .rcbr {
// p.warn('exiting $stack')
p.next()
break
}
p.next()
}
}
}
if p.tok.kind == .question {
p.next()
}
if !skip_os {
stmts = p.parse_block()
}
mut node := ast.CompIf{
is_not: is_not
stmts: p.parse_block()
pos: pos
val: val
stmts: stmts
}
if p.tok.kind == .dollar && p.peek_tok.kind == .key_else {
p.next()
@ -30,3 +73,56 @@ pub fn (p mut Parser) comp_if() ast.CompIf {
}
return node
}
fn os_from_string(os string) pref.OS {
match os {
'linux' {
return .linux
}
'windows' {
return .windows
}
'mac' {
return .mac
}
'macos' {
return .mac
}
'freebsd' {
return .freebsd
}
'openbsd' {
return .openbsd
}
'netbsd' {
return .netbsd
}
'dragonfly' {
return .dragonfly
}
'js' {
return .js
}
'solaris' {
return .solaris
}
'android' {
return .android
}
'msvc' {
// notice that `-os msvc` became `-cc msvc`
verror('use the flag `-cc msvc` to build using msvc')
}
'haiku' {
return .haiku
}
'linux_or_macos' {
return .linux
}
else {
panic('bad os $os')
}
}
// println('bad os $os') // todo panic?
return .linux
}

View File

@ -40,6 +40,7 @@ mut:
imports map[string]string
ast_imports []ast.Import
is_amp bool
returns bool
}
// for tests
@ -51,14 +52,14 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt {
pref: &pref.Preferences{}
scope: scope
// scope: &ast.Scope{start_pos: 0, parent: 0}
}
p.init_parse_fns()
p.read_first_token()
return p.stmt()
}
pub fn parse_file(path string, table &table.Table, comments_mode scanner.CommentsMode) ast.File {
pub fn parse_file(path string, table &table.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences) ast.File {
// println('parse_file("$path")')
// text := os.read_file(path) or {
// panic(err)
@ -69,13 +70,13 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment
scanner: scanner.new_scanner_file(path, comments_mode)
table: table
file_name: path
pref: &pref.Preferences{}
pref: pref //&pref.Preferences{}
scope: &ast.Scope{
start_pos: 0
parent: 0
}
// comments_mode: comments_mode
}
p.read_first_token()
// p.scope = &ast.Scope{start_pos: p.tok.position(), parent: 0}
@ -141,7 +142,7 @@ fn (q mut Queue) run() {
*/
pub fn parse_files(paths []string, table &table.Table) []ast.File {
pub fn parse_files(paths []string, table &table.Table, pref &pref.Preferences) []ast.File {
/*
println('\n\n\nparse_files()')
println(paths)
@ -162,7 +163,7 @@ pub fn parse_files(paths []string, table &table.Table) []ast.File {
mut files := []ast.File
for path in paths {
// println('parse_files $path')
files << parse_file(path, table, .skip_comments)
files << parse_file(path, table, .skip_comments, pref)
}
return files
}
@ -686,7 +687,7 @@ pub fn (p mut Parser) name_expr() ast.Expr {
p.expr_mod = ''
return ast.EnumVal{
enum_name: enum_name // lp.prepend_mod(enum_name)
val: val
pos: p.tok.position()
mod: mod
@ -776,7 +777,7 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
node = ast.SizeOf{
typ: sizeof_type
// type_name: type_name
}
}
.key_typeof {
@ -1044,7 +1045,7 @@ fn (p mut Parser) infix_expr(left ast.Expr) ast.Expr {
left: left
right: right
// right_type: typ
op: op
pos: pos
}
@ -1449,7 +1450,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl {
fields << ast.Field{
name: name
// typ: typ
}
exprs << expr
// TODO: once consts are fixed reg here & update in checker