2020-04-09 16:39:53 +02:00
|
|
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
2020-02-10 14:42:57 +01:00
|
|
|
module parser
|
2020-02-17 14:15:42 +01:00
|
|
|
|
2020-04-25 17:49:16 +02:00
|
|
|
import v.ast
|
|
|
|
import v.pref
|
|
|
|
import v.vmod
|
2020-02-17 14:15:42 +01:00
|
|
|
|
2020-03-27 14:44:30 +01:00
|
|
|
const (
|
2020-04-09 16:39:53 +02:00
|
|
|
supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
|
|
|
|
'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
|
2020-03-27 14:44:30 +01:00
|
|
|
)
|
|
|
|
|
2020-04-09 16:39:53 +02:00
|
|
|
// // #include, #flag, #v
|
2020-04-23 01:16:58 +02:00
|
|
|
fn (mut p Parser) hash() ast.HashStmt {
|
2020-04-09 16:39:53 +02:00
|
|
|
val := p.tok.lit
|
|
|
|
p.next()
|
|
|
|
if val.starts_with('flag') {
|
|
|
|
// #flag linux -lm
|
|
|
|
mut flag := val[5..]
|
|
|
|
// expand `@VROOT` to its absolute path
|
|
|
|
if flag.contains('@VROOT') {
|
2020-04-25 17:49:16 +02:00
|
|
|
vmod_file_location := vmod.mod_file_cacher.get(p.file_name_dir)
|
2020-04-10 12:01:06 +02:00
|
|
|
if vmod_file_location.vmod_file.len == 0 {
|
|
|
|
// There was no actual v.mod file found.
|
2020-04-25 17:49:16 +02:00
|
|
|
p.error('To use @VROOT, you need' + ' to have a "v.mod" file in ${p.file_name_dir},' +
|
2020-04-10 12:01:06 +02:00
|
|
|
' or in one of its parent folders.')
|
|
|
|
}
|
2020-04-25 17:49:16 +02:00
|
|
|
flag = flag.replace('@VROOT', vmod_file_location.vmod_folder)
|
2020-04-10 00:30:43 +02:00
|
|
|
}
|
2020-04-09 16:39:53 +02:00
|
|
|
for deprecated in ['@VMOD', '@VMODULE', '@VPATH', '@VLIB_PATH'] {
|
|
|
|
if flag.contains(deprecated) {
|
|
|
|
p.error('${deprecated} had been deprecated, use @VROOT instead.')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// println('adding flag "$flag"')
|
|
|
|
p.table.parse_cflag(flag, p.mod, p.pref.compile_defines_all) or {
|
|
|
|
p.error(err)
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
words := val.split(' ')
|
|
|
|
if words.len > 1 && words[1] in supported_platforms {
|
|
|
|
if p.pref.os == .mac && words[1] == 'darwin' {
|
|
|
|
p.pref.cflags += val.after('darwin')
|
|
|
|
}
|
|
|
|
}
|
2020-04-25 17:49:16 +02:00
|
|
|
*/
|
2020-04-09 16:39:53 +02:00
|
|
|
}
|
|
|
|
return ast.HashStmt{
|
|
|
|
val: val
|
2020-04-16 11:29:36 +02:00
|
|
|
mod: p.mod
|
2020-04-09 16:39:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-23 01:16:58 +02:00
|
|
|
fn (mut p Parser) comp_if() ast.CompIf {
|
2020-03-22 11:53:08 +01:00
|
|
|
pos := p.tok.position()
|
2020-02-17 14:15:42 +01:00
|
|
|
p.next()
|
|
|
|
p.check(.key_if)
|
2020-03-22 16:22:49 +01:00
|
|
|
is_not := p.tok.kind == .not
|
|
|
|
if is_not {
|
2020-02-17 14:15:42 +01:00
|
|
|
p.next()
|
|
|
|
}
|
2020-03-22 13:55:39 +01:00
|
|
|
val := p.check_name()
|
2020-04-26 09:17:13 +02:00
|
|
|
mut stmts := []ast.Stmt{}
|
2020-03-27 14:44:30 +01:00
|
|
|
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)
|
2020-04-27 15:08:04 +02:00
|
|
|
if !p.pref.is_fmt && ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) &&
|
2020-04-25 17:49:16 +02:00
|
|
|
!p.pref.output_cross_c {
|
2020-03-27 14:44:30 +01:00
|
|
|
skip_os = true
|
|
|
|
p.check(.lcbr)
|
2020-03-31 14:33:16 +02:00
|
|
|
// p.warn('skipping $if $val os=$os p.pref.os=$p.pref.os')
|
2020-03-27 14:44:30 +01:00
|
|
|
mut stack := 1
|
2020-04-25 17:49:16 +02:00
|
|
|
for {
|
2020-03-27 14:44:30 +01:00
|
|
|
if p.tok.kind == .key_return {
|
|
|
|
p.returns = true
|
|
|
|
}
|
|
|
|
if p.tok.kind == .lcbr {
|
|
|
|
stack++
|
2020-04-09 16:39:53 +02:00
|
|
|
} else if p.tok.kind == .rcbr {
|
2020-03-27 14:44:30 +01:00
|
|
|
stack--
|
|
|
|
}
|
|
|
|
if p.tok.kind == .eof {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if stack <= 0 && p.tok.kind == .rcbr {
|
|
|
|
// p.warn('exiting $stack')
|
|
|
|
p.next()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
p.next()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-23 16:52:44 +02:00
|
|
|
mut is_opt := false
|
2020-02-17 14:15:42 +01:00
|
|
|
if p.tok.kind == .question {
|
|
|
|
p.next()
|
2020-04-23 16:52:44 +02:00
|
|
|
is_opt = true
|
2020-02-17 14:15:42 +01:00
|
|
|
}
|
2020-03-27 14:44:30 +01:00
|
|
|
if !skip_os {
|
|
|
|
stmts = p.parse_block()
|
|
|
|
}
|
2020-03-22 10:12:43 +01:00
|
|
|
mut node := ast.CompIf{
|
2020-03-22 16:22:49 +01:00
|
|
|
is_not: is_not
|
2020-04-23 16:52:44 +02:00
|
|
|
is_opt: is_opt
|
2020-03-22 11:53:08 +01:00
|
|
|
pos: pos
|
2020-03-22 13:55:39 +01:00
|
|
|
val: val
|
2020-03-27 14:44:30 +01:00
|
|
|
stmts: stmts
|
2020-03-22 10:12:43 +01:00
|
|
|
}
|
2020-02-17 14:15:42 +01:00
|
|
|
if p.tok.kind == .dollar && p.peek_tok.kind == .key_else {
|
|
|
|
p.next()
|
2020-05-07 06:51:36 +02:00
|
|
|
p.next()
|
2020-03-22 14:54:31 +01:00
|
|
|
node.has_else = true
|
2020-03-22 10:12:43 +01:00
|
|
|
node.else_stmts = p.parse_block()
|
2020-02-17 14:15:42 +01:00
|
|
|
}
|
2020-03-22 10:12:43 +01:00
|
|
|
return node
|
2020-02-17 14:15:42 +01:00
|
|
|
}
|
2020-03-27 14:44:30 +01:00
|
|
|
|
2020-04-09 16:39:53 +02:00
|
|
|
// TODO import warning bug
|
2020-03-27 14:57:19 +01:00
|
|
|
const (
|
2020-04-09 16:39:53 +02:00
|
|
|
todo_delete_me = pref.OS.linux
|
2020-03-27 14:57:19 +01:00
|
|
|
)
|
|
|
|
|
2020-03-27 14:44:30 +01:00
|
|
|
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
|
|
|
|
}
|