cgen: treat the main module like any other v module
parent
81e4d3fd09
commit
78e1127d99
|
@ -8,7 +8,7 @@ uname -a
|
||||||
|
|
||||||
make -j4
|
make -j4
|
||||||
|
|
||||||
./v -version
|
./v version
|
||||||
|
|
||||||
du -s .
|
du -s .
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,12 @@ du -s .
|
||||||
|
|
||||||
ls -lat
|
ls -lat
|
||||||
|
|
||||||
./v test-compiler
|
##./v test-compiler
|
||||||
|
|
||||||
|
## try running the known failing tests first to get faster feedback
|
||||||
|
./v test vlib/builtin/string_test.v vlib/strings/builder_test.v
|
||||||
|
|
||||||
|
./v test-fixed
|
||||||
|
|
||||||
./v build-vbinaries
|
./v build-vbinaries
|
||||||
|
|
||||||
|
|
|
@ -55,15 +55,15 @@ jobs:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
# - name: Build V
|
- name: Build V
|
||||||
# uses: spytheman/docker_alpine_v@v7.0
|
uses: spytheman/docker_alpine_v@v7.0
|
||||||
# with:
|
with:
|
||||||
# entrypoint: .github/workflows/alpine.build.sh
|
entrypoint: .github/workflows/alpine.build.sh
|
||||||
|
|
||||||
# - name: Test V
|
- name: Test V
|
||||||
# uses: spytheman/docker_alpine_v@v7.0
|
uses: spytheman/docker_alpine_v@v7.0
|
||||||
# with:
|
with:
|
||||||
# entrypoint: .github/workflows/alpine.test.sh
|
entrypoint: .github/workflows/alpine.test.sh
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
@ -176,8 +176,6 @@ jobs:
|
||||||
../../vprod -backend x64 -o 1m 1m.v
|
../../vprod -backend x64 -o 1m 1m.v
|
||||||
echo "Running it..."
|
echo "Running it..."
|
||||||
ls
|
ls
|
||||||
- name: V self compilation with -autofree
|
|
||||||
run: ./v -o v2 -autofree cmd/v && ./v2 -o v3 -autofree cmd/v && ./v3 -o v4 -autofree cmd/v
|
|
||||||
# - name: SDL examples
|
# - name: SDL examples
|
||||||
# run: git clone --depth 1 https://github.com/vlang/sdl && cd sdl
|
# run: git clone --depth 1 https://github.com/vlang/sdl && cd sdl
|
||||||
|
|
||||||
|
@ -188,6 +186,18 @@ jobs:
|
||||||
# with:
|
# with:
|
||||||
# github-token: ${{ secrets.GITHUB_TOKEN }}
|
# github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
|
ubuntu-autofree-selfcompile:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
env:
|
||||||
|
VFLAGS: -cc gcc
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Build V
|
||||||
|
run: make -j4
|
||||||
|
- name: V self compilation with -autofree
|
||||||
|
run: ./v -o v2 -autofree cmd/v && ./v2 -o v3 -autofree cmd/v && ./v3 -o v4 -autofree cmd/v
|
||||||
|
|
||||||
ubuntu-musl:
|
ubuntu-musl:
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-18.04
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -3,3 +3,7 @@ module main
|
||||||
// This prelude is loaded in every v program compiled with -live,
|
// This prelude is loaded in every v program compiled with -live,
|
||||||
// in both the main executable, and in the shared library.
|
// in both the main executable, and in the shared library.
|
||||||
import live
|
import live
|
||||||
|
|
||||||
|
const (
|
||||||
|
no_warning_live_is_used = live.is_used
|
||||||
|
)
|
||||||
|
|
|
@ -3,3 +3,7 @@ module main
|
||||||
// This prelude is loaded in every v program compiled with -live,
|
// This prelude is loaded in every v program compiled with -live,
|
||||||
// but only for the main executable.
|
// but only for the main executable.
|
||||||
import live.executable
|
import live.executable
|
||||||
|
|
||||||
|
const (
|
||||||
|
no_warning_live_executable_is_used = executable.is_used
|
||||||
|
)
|
||||||
|
|
|
@ -3,3 +3,7 @@ module main
|
||||||
// This prelude is loaded in every v program compiled with -live,
|
// This prelude is loaded in every v program compiled with -live,
|
||||||
// but only for the shared library.
|
// but only for the shared library.
|
||||||
import live.shared
|
import live.shared
|
||||||
|
|
||||||
|
const (
|
||||||
|
no_warning_live_shared_is_used = shared.is_used
|
||||||
|
)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import term
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// / This file will get compiled as part of the main program,
|
// / This file will get compiled as part of the main program,
|
||||||
// / for a _test.v file.
|
// / for a _test.v file.
|
||||||
|
@ -11,7 +12,7 @@ import os
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// TODO copy pasta builtin.v fn ___print_assert_failure
|
// TODO copy pasta builtin.v fn ___print_assert_failure
|
||||||
fn cb_assertion_failed(i &VAssertMetaInfo) {
|
fn cb_assertion_failed(i &VAssertMetaInfo) {
|
||||||
// color_on := term.can_show_color_on_stderr()
|
use_color := term.can_show_color_on_stderr()
|
||||||
use_relative_paths := match os.getenv('VERROR_PATHS') {
|
use_relative_paths := match os.getenv('VERROR_PATHS') {
|
||||||
'absolute' {
|
'absolute' {
|
||||||
false
|
false
|
||||||
|
@ -20,18 +21,22 @@ fn cb_assertion_failed(i &VAssertMetaInfo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final_filename := if use_relative_paths { i.fpath } else { os.real_path(i.fpath) }
|
final_filename := if use_relative_paths { i.fpath } else { os.real_path(i.fpath) }
|
||||||
final_funcname := i.fn_name.replace('main__', '').replace('__', '.')
|
final_funcname := i.fn_name.replace('main.', '').replace('__', '.')
|
||||||
|
final_src := if use_color { term.bold(i.src) } else { i.src }
|
||||||
eprintln('')
|
eprintln('')
|
||||||
eprintln('$final_filename:${i.line_nr+1}: failed assert in ${final_funcname}')
|
eprintln('$final_filename:${i.line_nr+1}: failed assert in function ${final_funcname}')
|
||||||
eprintln('Source : ${i.src}')
|
eprintln('Source : `${final_src}`')
|
||||||
if i.op.len > 0 && i.op != 'call' {
|
if i.op.len > 0 && i.op != 'call' {
|
||||||
eprintln(' left value: ${i.llabel} = ${i.lvalue}')
|
mut slvalue := '${i.lvalue}'
|
||||||
if i.rlabel == i.rvalue {
|
mut srvalue := '${i.rvalue}'
|
||||||
eprintln(' right value: $i.rlabel')
|
lpostfix := if slvalue == i.llabel { '.' } else { '<= `${i.llabel}`' }
|
||||||
}
|
rpostfix := if srvalue == i.rlabel { '.' } else { '<= `${i.rlabel}`' }
|
||||||
else {
|
if use_color {
|
||||||
eprintln(' right value: ${i.rlabel} = ${i.rvalue}')
|
slvalue = term.bold(term.yellow(slvalue))
|
||||||
|
srvalue = term.bold(term.yellow(srvalue))
|
||||||
}
|
}
|
||||||
|
eprintln(' left value: ${slvalue} ${lpostfix}')
|
||||||
|
eprintln(' right value: ${srvalue} ${rpostfix}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ fn start_testing(total_number_of_tests int, vfilename string) BenchedTests {
|
||||||
|
|
||||||
// Called before each test_ function, defined in file_test.v
|
// Called before each test_ function, defined in file_test.v
|
||||||
fn (mut b BenchedTests) testing_step_start(stepfunc string) {
|
fn (mut b BenchedTests) testing_step_start(stepfunc string) {
|
||||||
b.step_func_name = stepfunc.replace('main__', '').replace('__', '.')
|
b.step_func_name = stepfunc.replace('main.', '').replace('__', '.')
|
||||||
b.oks = C.g_test_oks
|
b.oks = C.g_test_oks
|
||||||
b.fails = C.g_test_fails
|
b.fails = C.g_test_fails
|
||||||
b.bench.step()
|
b.bench.step()
|
||||||
|
|
|
@ -15,6 +15,7 @@ const (
|
||||||
'vlib/sqlite/sqlite_test.v',
|
'vlib/sqlite/sqlite_test.v',
|
||||||
'vlib/orm/orm_test.v',
|
'vlib/orm/orm_test.v',
|
||||||
'vlib/clipboard/clipboard_test.v',
|
'vlib/clipboard/clipboard_test.v',
|
||||||
|
'vlib/v/gen/js/jsgen_test.v',
|
||||||
]
|
]
|
||||||
skip_on_linux = []string{}
|
skip_on_linux = []string{}
|
||||||
skip_on_non_linux = [
|
skip_on_non_linux = [
|
||||||
|
|
|
@ -67,8 +67,8 @@ pub fn (input BitField) str() string {
|
||||||
pub fn new(size int) BitField {
|
pub fn new(size int) BitField {
|
||||||
output := BitField{
|
output := BitField{
|
||||||
size: size
|
size: size
|
||||||
//field: *u32(calloc(bitnslots(size) * slot_size / 8))
|
//field: *u32(calloc(zbitnslots(size) * slot_size / 8))
|
||||||
field: []u32{len:bitnslots(size)}
|
field: []u32{len:zbitnslots(size)}
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ pub fn (mut instance BitField) clear_bit(bitnr int) {
|
||||||
|
|
||||||
// set_all sets all bits in the array to 1.
|
// set_all sets all bits in the array to 1.
|
||||||
pub fn (mut instance BitField) set_all() {
|
pub fn (mut instance BitField) set_all() {
|
||||||
for i in 0..bitnslots(instance.size) {
|
for i in 0..zbitnslots(instance.size) {
|
||||||
instance.field[i] = u32(-1)
|
instance.field[i] = u32(-1)
|
||||||
}
|
}
|
||||||
instance.clear_tail()
|
instance.clear_tail()
|
||||||
|
@ -113,7 +113,7 @@ pub fn (mut instance BitField) set_all() {
|
||||||
|
|
||||||
// clear_all clears (sets to zero) all bits in the array.
|
// clear_all clears (sets to zero) all bits in the array.
|
||||||
pub fn (mut instance BitField) clear_all() {
|
pub fn (mut instance BitField) clear_all() {
|
||||||
for i in 0..bitnslots(instance.size) {
|
for i in 0..zbitnslots(instance.size) {
|
||||||
instance.field[i] = u32(0)
|
instance.field[i] = u32(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ pub fn (mut instance BitField) toggle_bit(bitnr int) {
|
||||||
// the tail of the longer one is ignored.
|
// the tail of the longer one is ignored.
|
||||||
pub fn bf_and(input1 BitField, input2 BitField) BitField {
|
pub fn bf_and(input1 BitField, input2 BitField) BitField {
|
||||||
size := min(input1.size, input2.size)
|
size := min(input1.size, input2.size)
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := zbitnslots(size)
|
||||||
mut output := new(size)
|
mut output := new(size)
|
||||||
for i in 0..bitnslots {
|
for i in 0..bitnslots {
|
||||||
output.field[i] = input1.field[i] & input2.field[i]
|
output.field[i] = input1.field[i] & input2.field[i]
|
||||||
|
@ -144,7 +144,7 @@ pub fn bf_and(input1 BitField, input2 BitField) BitField {
|
||||||
// bf_not toggles all bits in a bit array and returns the result as a new array.
|
// bf_not toggles all bits in a bit array and returns the result as a new array.
|
||||||
pub fn bf_not(input BitField) BitField {
|
pub fn bf_not(input BitField) BitField {
|
||||||
size := input.size
|
size := input.size
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := zbitnslots(size)
|
||||||
mut output := new(size)
|
mut output := new(size)
|
||||||
for i in 0..bitnslots {
|
for i in 0..bitnslots {
|
||||||
output.field[i] = ~input.field[i]
|
output.field[i] = ~input.field[i]
|
||||||
|
@ -158,7 +158,7 @@ pub fn bf_not(input BitField) BitField {
|
||||||
// the tail of the longer one is ignored.
|
// the tail of the longer one is ignored.
|
||||||
pub fn bf_or(input1 BitField, input2 BitField) BitField {
|
pub fn bf_or(input1 BitField, input2 BitField) BitField {
|
||||||
size := min(input1.size, input2.size)
|
size := min(input1.size, input2.size)
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := zbitnslots(size)
|
||||||
mut output := new(size)
|
mut output := new(size)
|
||||||
for i in 0..bitnslots {
|
for i in 0..bitnslots {
|
||||||
output.field[i] = input1.field[i] | input2.field[i]
|
output.field[i] = input1.field[i] | input2.field[i]
|
||||||
|
@ -172,7 +172,7 @@ pub fn bf_or(input1 BitField, input2 BitField) BitField {
|
||||||
// the tail of the longer one is ignored.
|
// the tail of the longer one is ignored.
|
||||||
pub fn bf_xor(input1 BitField, input2 BitField) BitField {
|
pub fn bf_xor(input1 BitField, input2 BitField) BitField {
|
||||||
size := min(input1.size, input2.size)
|
size := min(input1.size, input2.size)
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := zbitnslots(size)
|
||||||
mut output := new(size)
|
mut output := new(size)
|
||||||
for i in 0..bitnslots {
|
for i in 0..bitnslots {
|
||||||
output.field[i] = input1.field[i] ^ input2.field[i]
|
output.field[i] = input1.field[i] ^ input2.field[i]
|
||||||
|
@ -186,7 +186,7 @@ pub fn join(input1 BitField, input2 BitField) BitField {
|
||||||
output_size := input1.size + input2.size
|
output_size := input1.size + input2.size
|
||||||
mut output := new(output_size)
|
mut output := new(output_size)
|
||||||
// copy the first input to output as is
|
// copy the first input to output as is
|
||||||
for i in 0..bitnslots(input1.size) {
|
for i in 0..zbitnslots(input1.size) {
|
||||||
output.field[i] = input1.field[i]
|
output.field[i] = input1.field[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ pub fn join(input1 BitField, input2 BitField) BitField {
|
||||||
offset_bit := input1.size % slot_size
|
offset_bit := input1.size % slot_size
|
||||||
offset_slot := input1.size / slot_size
|
offset_slot := input1.size / slot_size
|
||||||
|
|
||||||
for i in 0..bitnslots(input2.size) {
|
for i in 0..zbitnslots(input2.size) {
|
||||||
output.field[i + offset_slot] |=
|
output.field[i + offset_slot] |=
|
||||||
u32(input2.field[i] << u32(offset_bit))
|
u32(input2.field[i] << u32(offset_bit))
|
||||||
}
|
}
|
||||||
|
@ -213,12 +213,12 @@ pub fn join(input1 BitField, input2 BitField) BitField {
|
||||||
* If offset_bit is zero, no additional copies needed.
|
* If offset_bit is zero, no additional copies needed.
|
||||||
*/
|
*/
|
||||||
if (output_size - 1) % slot_size < (input2.size - 1) % slot_size {
|
if (output_size - 1) % slot_size < (input2.size - 1) % slot_size {
|
||||||
for i in 0..bitnslots(input2.size) {
|
for i in 0..zbitnslots(input2.size) {
|
||||||
output.field[i + offset_slot + 1] |=
|
output.field[i + offset_slot + 1] |=
|
||||||
u32(input2.field[i] >> u32(slot_size - offset_bit))
|
u32(input2.field[i] >> u32(slot_size - offset_bit))
|
||||||
}
|
}
|
||||||
} else if (output_size - 1) % slot_size > (input2.size - 1) % slot_size {
|
} else if (output_size - 1) % slot_size > (input2.size - 1) % slot_size {
|
||||||
for i in 0..bitnslots(input2.size) - 1 {
|
for i in 0..zbitnslots(input2.size) - 1 {
|
||||||
output.field[i + offset_slot + 1] |=
|
output.field[i + offset_slot + 1] |=
|
||||||
u32(input2.field[i] >> u32(slot_size - offset_bit))
|
u32(input2.field[i] >> u32(slot_size - offset_bit))
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ pub fn (instance BitField) get_size() int {
|
||||||
|
|
||||||
// clone creates a copy of a bit array.
|
// clone creates a copy of a bit array.
|
||||||
pub fn (instance BitField) clone() BitField {
|
pub fn (instance BitField) clone() BitField {
|
||||||
bitnslots := bitnslots(instance.size)
|
bitnslots := zbitnslots(instance.size)
|
||||||
mut output := new(instance.size)
|
mut output := new(instance.size)
|
||||||
for i in 0..bitnslots {
|
for i in 0..bitnslots {
|
||||||
output.field[i] = instance.field[i]
|
output.field[i] = instance.field[i]
|
||||||
|
@ -245,7 +245,7 @@ pub fn (instance BitField) clone() BitField {
|
||||||
// identical by length and contents and 'false' otherwise.
|
// identical by length and contents and 'false' otherwise.
|
||||||
pub fn (instance BitField) cmp(input BitField) bool {
|
pub fn (instance BitField) cmp(input BitField) bool {
|
||||||
if instance.size != input.size {return false}
|
if instance.size != input.size {return false}
|
||||||
for i in 0..bitnslots(instance.size) {
|
for i in 0..zbitnslots(instance.size) {
|
||||||
if instance.field[i] != input.field[i] {return false}
|
if instance.field[i] != input.field[i] {return false}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -254,7 +254,7 @@ pub fn (instance BitField) cmp(input BitField) bool {
|
||||||
// pop_count returns the number of set bits (ones) in the array.
|
// pop_count returns the number of set bits (ones) in the array.
|
||||||
pub fn (instance BitField) pop_count() int {
|
pub fn (instance BitField) pop_count() int {
|
||||||
size := instance.size
|
size := instance.size
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := zbitnslots(size)
|
||||||
tail := size % slot_size
|
tail := size % slot_size
|
||||||
mut count := 0
|
mut count := 0
|
||||||
for i in 0..bitnslots - 1 {
|
for i in 0..bitnslots - 1 {
|
||||||
|
@ -318,7 +318,7 @@ pub fn (input BitField) slice(_start int, _end int) BitField {
|
||||||
end_offset := (end - 1) % slot_size
|
end_offset := (end - 1) % slot_size
|
||||||
start_slot := start / slot_size
|
start_slot := start / slot_size
|
||||||
end_slot := (end - 1) / slot_size
|
end_slot := (end - 1) / slot_size
|
||||||
output_slots := bitnslots(end - start)
|
output_slots := zbitnslots(end - start)
|
||||||
|
|
||||||
if output_slots > 1 {
|
if output_slots > 1 {
|
||||||
if start_offset != 0 {
|
if start_offset != 0 {
|
||||||
|
@ -371,7 +371,7 @@ pub fn (input BitField) slice(_start int, _end int) BitField {
|
||||||
// last, the second with the last but one and so on).
|
// last, the second with the last but one and so on).
|
||||||
pub fn (instance BitField) reverse() BitField {
|
pub fn (instance BitField) reverse() BitField {
|
||||||
size := instance.size
|
size := instance.size
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := zbitnslots(size)
|
||||||
mut output := new(size)
|
mut output := new(size)
|
||||||
for i:= 0; i < (bitnslots - 1); i++ {
|
for i:= 0; i < (bitnslots - 1); i++ {
|
||||||
for j in 0..slot_size {
|
for j in 0..slot_size {
|
||||||
|
@ -391,9 +391,9 @@ pub fn (instance BitField) reverse() BitField {
|
||||||
|
|
||||||
// resize changes the size of the bit array to 'new_size'.
|
// resize changes the size of the bit array to 'new_size'.
|
||||||
pub fn (mut instance BitField) resize(new_size int) {
|
pub fn (mut instance BitField) resize(new_size int) {
|
||||||
new_bitnslots := bitnslots(new_size)
|
new_bitnslots := zbitnslots(new_size)
|
||||||
old_size := instance.size
|
old_size := instance.size
|
||||||
old_bitnslots := bitnslots(old_size)
|
old_bitnslots := zbitnslots(old_size)
|
||||||
mut field := []u32{len:new_bitnslots}
|
mut field := []u32{len:new_bitnslots}
|
||||||
for i := 0; i < old_bitnslots && i < new_bitnslots; i++ {
|
for i := 0; i < old_bitnslots && i < new_bitnslots; i++ {
|
||||||
field[i] = instance.field[i]
|
field[i] = instance.field[i]
|
||||||
|
@ -439,7 +439,7 @@ fn (mut instance BitField) clear_tail() {
|
||||||
// create a mask for the tail
|
// create a mask for the tail
|
||||||
mask := u32((1 << tail) - 1)
|
mask := u32((1 << tail) - 1)
|
||||||
// clear the extra bits
|
// clear the extra bits
|
||||||
instance.field[bitnslots(instance.size) - 1] = instance.field[bitnslots(instance.size) - 1] & mask
|
instance.field[zbitnslots(instance.size) - 1] = instance.field[zbitnslots(instance.size) - 1] & mask
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,6 +460,6 @@ fn min(input1 int, input2 int) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bitnslots(length int) int {
|
fn zbitnslots(length int) int {
|
||||||
return (length - 1) / slot_size + 1
|
return (length - 1) / slot_size + 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,22 +168,22 @@ pub fn v_realloc(b byteptr, n int) byteptr {
|
||||||
if ptr == 0 {
|
if ptr == 0 {
|
||||||
panic('realloc($n) failed')
|
panic('realloc($n) failed')
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr
|
return ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[unsafe_fn]
|
||||||
pub fn v_calloc(n int) byteptr {
|
pub fn v_calloc(n int) byteptr {
|
||||||
return C.calloc(n, 1)
|
return C.calloc(1, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[unsafe_fn]
|
||||||
pub fn vcalloc(n int) byteptr {
|
pub fn vcalloc(n int) byteptr {
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
panic('calloc(<=0)')
|
panic('calloc(<=0)')
|
||||||
} else if n == 0 {
|
} else if n == 0 {
|
||||||
return byteptr(0)
|
return byteptr(0)
|
||||||
} else {
|
|
||||||
return C.calloc(n, 1)
|
|
||||||
}
|
}
|
||||||
|
return C.calloc(1, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
[unsafe_fn]
|
[unsafe_fn]
|
||||||
|
@ -223,7 +223,7 @@ fn __as_cast(obj voidptr, obj_type, expected_type int) voidptr {
|
||||||
|
|
||||||
// VAssertMetaInfo is used during assertions. An instance of it
|
// VAssertMetaInfo is used during assertions. An instance of it
|
||||||
// is filled in by compile time generated code, when an assertion fails.
|
// is filled in by compile time generated code, when an assertion fails.
|
||||||
struct VAssertMetaInfo {
|
pub struct VAssertMetaInfo {
|
||||||
pub:
|
pub:
|
||||||
fpath string // the source file path of the assertion
|
fpath string // the source file path of the assertion
|
||||||
line_nr int // the line number of the assertion
|
line_nr int // the line number of the assertion
|
||||||
|
|
|
@ -126,9 +126,9 @@ fn test_various_map_value() {
|
||||||
m12['test'] = f64(0.0)
|
m12['test'] = f64(0.0)
|
||||||
assert m12['test'] == f64(0.0)
|
assert m12['test'] == f64(0.0)
|
||||||
|
|
||||||
mut m13 := map[string]rune
|
//mut m13 := map[string]rune
|
||||||
m13['test'] = rune(0)
|
//m13['test'] = rune(0)
|
||||||
assert m13['test'] == rune(0)
|
//assert m13['test'] == rune(0)
|
||||||
|
|
||||||
mut m14 := map[string]voidptr
|
mut m14 := map[string]voidptr
|
||||||
m14['test'] = voidptr(0)
|
m14['test'] = voidptr(0)
|
||||||
|
|
|
@ -1369,7 +1369,11 @@ pub fn (s string) fields() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s string) map(func fn(byte) byte) string {
|
pub fn (s string) map(func fn(byte) byte) string {
|
||||||
return string(s.bytes().map(func(it)))
|
mut res := malloc(s.len + 1)
|
||||||
|
for i in 0..s.len {
|
||||||
|
res[i] = func(s[i])
|
||||||
|
}
|
||||||
|
return tos(res, s.len)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows multi-line strings to be formatted in a way that removes white-space
|
// Allows multi-line strings to be formatted in a way that removes white-space
|
||||||
|
|
|
@ -762,10 +762,20 @@ fn test_string_map() {
|
||||||
$if windows {
|
$if windows {
|
||||||
return // TODO
|
return // TODO
|
||||||
}
|
}
|
||||||
a := 'Hello'.map(fn (b byte) byte {
|
original := 'Hello'
|
||||||
|
println('original.len = $original.len')
|
||||||
|
a := original.map(fn (b byte) byte {
|
||||||
return b + 1
|
return b + 1
|
||||||
})
|
})
|
||||||
assert a == 'Ifmmp'
|
expected := 'Ifmmp'
|
||||||
|
println('a[0] = ' + a[0].str())
|
||||||
|
println('a[1] = ' + a[1].str())
|
||||||
|
println('a[2] = ' + a[2].str())
|
||||||
|
println('a[3] = ' + a[3].str())
|
||||||
|
println('a[4] = ' + a[4].str())
|
||||||
|
println('a.len = $a.len')
|
||||||
|
assert a.len == expected.len
|
||||||
|
assert a == expected
|
||||||
|
|
||||||
assert 'foo'.map(foo) == r'\ee'
|
assert 'foo'.map(foo) == r'\ee'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
module live
|
module live
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
is_used = 1
|
||||||
|
)
|
||||||
|
|
||||||
pub type FNLinkLiveSymbols = fn (linkcb voidptr)
|
pub type FNLinkLiveSymbols = fn (linkcb voidptr)
|
||||||
|
|
||||||
pub type FNLiveReloadCB = fn (info &LiveReloadInfo)
|
pub type FNLiveReloadCB = fn (info &LiveReloadInfo)
|
||||||
|
|
|
@ -6,6 +6,10 @@ import dl
|
||||||
import strconv
|
import strconv
|
||||||
import live
|
import live
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
is_used = 1
|
||||||
|
)
|
||||||
|
|
||||||
// The live reloader code is implemented here.
|
// The live reloader code is implemented here.
|
||||||
|
|
||||||
// NB: new_live_reload_info will be called by generated C code inside main()
|
// NB: new_live_reload_info will be called by generated C code inside main()
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
module shared
|
module shared
|
||||||
|
|
||||||
import live
|
import live
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
is_used = 1
|
||||||
|
)
|
||||||
|
|
|
@ -203,10 +203,10 @@ pub fn mean_absdev(arr []f64) f64 {
|
||||||
if arr.len == 0 {
|
if arr.len == 0 {
|
||||||
return f64(0)
|
return f64(0)
|
||||||
}
|
}
|
||||||
mean := mean(arr)
|
amean := mean(arr)
|
||||||
mut sum := f64(0)
|
mut sum := f64(0)
|
||||||
for v in arr {
|
for v in arr {
|
||||||
sum += math.abs(v-mean)
|
sum += math.abs(v-amean)
|
||||||
}
|
}
|
||||||
return sum/f64(arr.len)
|
return sum/f64(arr.len)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
module main
|
|
||||||
|
|
||||||
import net.ftp
|
import net.ftp
|
||||||
|
|
||||||
// NB: this function makes network calls to external servers,
|
// NB: this function makes network calls to external servers,
|
||||||
|
|
|
@ -49,21 +49,26 @@ pub fn (mut b Builder) go_back(n int) {
|
||||||
b.len -= n
|
b.len -= n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bytes2string(b []byte) string {
|
||||||
|
mut copy := b.clone()
|
||||||
|
copy << `\0`
|
||||||
|
res := tos(copy.data, copy.len-1)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut b Builder) cut_last(n int) string {
|
pub fn (mut b Builder) cut_last(n int) string {
|
||||||
buf := b.buf[b.len-n..]
|
res := bytes2string( b.buf[b.len-n..] )
|
||||||
s := string(buf.clone())
|
|
||||||
b.buf.trim(b.buf.len-n)
|
b.buf.trim(b.buf.len-n)
|
||||||
b.len -= n
|
b.len -= n
|
||||||
return s
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn (mut b Builder) cut_to(pos int) string {
|
pub fn (mut b Builder) cut_to(pos int) string {
|
||||||
buf := b.buf[pos..]
|
res := bytes2string( b.buf[pos..] )
|
||||||
s := string(buf.clone())
|
|
||||||
b.buf.trim(pos)
|
b.buf.trim(pos)
|
||||||
b.len = pos
|
b.len = pos
|
||||||
return s
|
return res
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -88,8 +93,7 @@ pub fn (b &Builder) last_n(n int) string {
|
||||||
if n > b.len {
|
if n > b.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
buf := b.buf[b.len-n..]
|
return bytes2string( b.buf[b.len-n..] )
|
||||||
return string(buf.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buf == 'hello world'
|
// buf == 'hello world'
|
||||||
|
@ -98,10 +102,7 @@ pub fn (b &Builder) after(n int) string {
|
||||||
if n >= b.len {
|
if n >= b.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
buf := b.buf[n..]
|
return bytes2string( b.buf[n..] )
|
||||||
mut copy := buf.clone()
|
|
||||||
copy << `\0`
|
|
||||||
return string(copy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: in order to avoid memleaks and additional memory copies, after a call to b.str(),
|
// NB: in order to avoid memleaks and additional memory copies, after a call to b.str(),
|
||||||
|
|
|
@ -6,7 +6,8 @@ fn test_sb() {
|
||||||
sb.write('!')
|
sb.write('!')
|
||||||
sb.write('hello')
|
sb.write('hello')
|
||||||
assert sb.len == 8
|
assert sb.len == 8
|
||||||
assert sb.str() == 'hi!hello'
|
sb_end := sb.str()
|
||||||
|
assert sb_end == 'hi!hello'
|
||||||
assert sb.len == 0
|
assert sb.len == 0
|
||||||
///
|
///
|
||||||
sb = strings.new_builder(10)
|
sb = strings.new_builder(10)
|
||||||
|
@ -19,39 +20,33 @@ fn test_sb() {
|
||||||
// TODO msvc bug
|
// TODO msvc bug
|
||||||
sb = strings.new_builder(10)
|
sb = strings.new_builder(10)
|
||||||
sb.write('123456')
|
sb.write('123456')
|
||||||
assert sb.cut_last(2) == '56'
|
last_2 := sb.cut_last(2)
|
||||||
assert sb.str() == '1234'
|
assert last_2 == '56'
|
||||||
|
final_sb := sb.str()
|
||||||
|
assert final_sb == '1234'
|
||||||
}
|
}
|
||||||
///
|
|
||||||
/*
|
|
||||||
sb = strings.new_builder(10)
|
|
||||||
sb.write('123456')
|
|
||||||
x := sb.cut_to(2)
|
|
||||||
assert x == '456'
|
|
||||||
assert sb.str() == '123'
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
n = 100000
|
maxn = 100000
|
||||||
)
|
)
|
||||||
|
|
||||||
fn test_big_sb() {
|
fn test_big_sb() {
|
||||||
mut sb := strings.new_builder(100)
|
mut sb := strings.new_builder(100)
|
||||||
mut sb2 := strings.new_builder(10000)
|
mut sb2 := strings.new_builder(10000)
|
||||||
for i in 0..n {
|
for i in 0..maxn {
|
||||||
sb.writeln(i.str())
|
sb.writeln(i.str())
|
||||||
sb2.write('+')
|
sb2.write('+')
|
||||||
}
|
}
|
||||||
s := sb.str()
|
s := sb.str()
|
||||||
lines := s.split_into_lines()
|
lines := s.split_into_lines()
|
||||||
assert lines.len == n
|
assert lines.len == maxn
|
||||||
assert lines[0] == '0'
|
assert lines[0] == '0'
|
||||||
assert lines[1] == '1'
|
assert lines[1] == '1'
|
||||||
assert lines[777] == '777'
|
assert lines[777] == '777'
|
||||||
assert lines[98765] == '98765'
|
assert lines[98765] == '98765'
|
||||||
println(sb2.len)
|
println(sb2.len)
|
||||||
assert sb2.len == n
|
assert sb2.len == maxn
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,5 +59,6 @@ fn test_byte_write() {
|
||||||
count++
|
count++
|
||||||
assert count == sb.len
|
assert count == sb.len
|
||||||
}
|
}
|
||||||
assert sb.str() == temp_str
|
sb_final := sb.str()
|
||||||
|
assert sb_final == temp_str
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,13 +48,13 @@ pub fn (t Time) md() string {
|
||||||
// - a date string in "MMM D HH:MM" format (24h) for date of current year
|
// - a date string in "MMM D HH:MM" format (24h) for date of current year
|
||||||
// - a date string formatted with format function for other dates
|
// - a date string formatted with format function for other dates
|
||||||
pub fn (t Time) clean() string {
|
pub fn (t Time) clean() string {
|
||||||
now := time.now()
|
znow := time.now()
|
||||||
// Today
|
// Today
|
||||||
if t.month == now.month && t.year == now.year && t.day == now.day {
|
if t.month == znow.month && t.year == znow.year && t.day == znow.day {
|
||||||
return t.get_fmt_time_str(.hhmm24)
|
return t.get_fmt_time_str(.hhmm24)
|
||||||
}
|
}
|
||||||
// This year
|
// This year
|
||||||
if t.year == now.year {
|
if t.year == znow.year {
|
||||||
return t.get_fmt_str(.space, .hhmm24, .mmmd)
|
return t.get_fmt_str(.space, .hhmm24, .mmmd)
|
||||||
}
|
}
|
||||||
return t.format()
|
return t.format()
|
||||||
|
@ -65,13 +65,13 @@ pub fn (t Time) clean() string {
|
||||||
// - a date string in "MMM D HH:MM" format (12h) for date of current year
|
// - a date string in "MMM D HH:MM" format (12h) for date of current year
|
||||||
// - a date string formatted with format function for other dates
|
// - a date string formatted with format function for other dates
|
||||||
pub fn (t Time) clean12() string {
|
pub fn (t Time) clean12() string {
|
||||||
now := time.now()
|
znow := time.now()
|
||||||
// Today
|
// Today
|
||||||
if t.month == now.month && t.year == now.year && t.day == now.day {
|
if t.month == znow.month && t.year == znow.year && t.day == znow.day {
|
||||||
return t.get_fmt_time_str(.hhmm12)
|
return t.get_fmt_time_str(.hhmm12)
|
||||||
}
|
}
|
||||||
// This year
|
// This year
|
||||||
if t.year == now.year {
|
if t.year == znow.year {
|
||||||
return t.get_fmt_str(.space, .hhmm12, .mmmd)
|
return t.get_fmt_str(.space, .hhmm12, .mmmd)
|
||||||
}
|
}
|
||||||
return t.format()
|
return t.format()
|
||||||
|
|
|
@ -189,8 +189,8 @@ fn since(t Time) int {
|
||||||
// relative returns a string representation of difference between time
|
// relative returns a string representation of difference between time
|
||||||
// and current time.
|
// and current time.
|
||||||
pub fn (t Time) relative() string {
|
pub fn (t Time) relative() string {
|
||||||
now := time.now()
|
znow := time.now()
|
||||||
secs := now.unix - t.unix
|
secs := znow.unix - t.unix
|
||||||
if secs <= 30 {
|
if secs <= 30 {
|
||||||
// right now or in the future
|
// right now or in the future
|
||||||
// TODO handle time in the future
|
// TODO handle time in the future
|
||||||
|
@ -227,8 +227,8 @@ pub fn (t Time) relative() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t Time) relative_short() string {
|
pub fn (t Time) relative_short() string {
|
||||||
now := time.now()
|
znow := time.now()
|
||||||
secs := now.unix - t.unix
|
secs := znow.unix - t.unix
|
||||||
if secs <= 30 {
|
if secs <= 30 {
|
||||||
// right now or in the future
|
// right now or in the future
|
||||||
// TODO handle time in the future
|
// TODO handle time in the future
|
||||||
|
|
|
@ -323,10 +323,10 @@ pub struct File {
|
||||||
pub:
|
pub:
|
||||||
path string
|
path string
|
||||||
mod Module
|
mod Module
|
||||||
stmts []Stmt
|
|
||||||
scope &Scope
|
scope &Scope
|
||||||
global_scope &Scope
|
global_scope &Scope
|
||||||
pub mut:
|
pub mut:
|
||||||
|
stmts []Stmt
|
||||||
imports []Import
|
imports []Import
|
||||||
errors []errors.Error
|
errors []errors.Error
|
||||||
warnings []errors.Warning
|
warnings []errors.Warning
|
||||||
|
@ -361,9 +361,9 @@ pub struct Ident {
|
||||||
pub:
|
pub:
|
||||||
language table.Language
|
language table.Language
|
||||||
tok_kind token.Kind
|
tok_kind token.Kind
|
||||||
mod string
|
|
||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
|
mod string
|
||||||
name string
|
name string
|
||||||
kind IdentKind
|
kind IdentKind
|
||||||
info IdentInfo
|
info IdentInfo
|
||||||
|
@ -753,8 +753,11 @@ pub mut:
|
||||||
|
|
||||||
pub struct SizeOf {
|
pub struct SizeOf {
|
||||||
pub:
|
pub:
|
||||||
|
is_type bool
|
||||||
typ table.Type
|
typ table.Type
|
||||||
type_name string
|
type_name string
|
||||||
|
expr Expr
|
||||||
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Likely {
|
pub struct Likely {
|
||||||
|
@ -933,7 +936,9 @@ pub fn (expr Expr) position() token.Position {
|
||||||
SelectorExpr {
|
SelectorExpr {
|
||||||
return expr.pos
|
return expr.pos
|
||||||
}
|
}
|
||||||
// ast.SizeOf { }
|
SizeOf {
|
||||||
|
return expr.pos
|
||||||
|
}
|
||||||
StringLiteral {
|
StringLiteral {
|
||||||
return expr.pos
|
return expr.pos
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,7 @@ pub fn (v Builder) get_user_files() []string {
|
||||||
if line[0] == `/` && line[1] == `/` {
|
if line[0] == `/` && line[1] == `/` {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if line.starts_with('module ') && !line.starts_with('module main') {
|
if line.starts_with('module ') {
|
||||||
is_internal_module_test = true
|
is_internal_module_test = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,15 +105,33 @@ pub fn (mut c Checker) check2(ast_file ast.File) []errors.Error {
|
||||||
pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||||
mut has_main_mod_file := false
|
mut has_main_mod_file := false
|
||||||
mut has_main_fn := false
|
mut has_main_fn := false
|
||||||
for file in ast_files {
|
|
||||||
|
mut files_from_main_module := []&ast.File{}
|
||||||
|
for i in 0..ast_files.len {
|
||||||
|
file := &ast_files[i]
|
||||||
c.check(file)
|
c.check(file)
|
||||||
if file.mod.name == 'main' {
|
if file.mod.name == 'main' {
|
||||||
|
files_from_main_module << file
|
||||||
has_main_mod_file = true
|
has_main_mod_file = true
|
||||||
if c.check_file_in_main(file) {
|
if c.check_file_in_main(file) {
|
||||||
has_main_fn = true
|
has_main_fn = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if has_main_mod_file && !has_main_fn && files_from_main_module.len > 0 {
|
||||||
|
if c.pref.is_script && !c.pref.is_test {
|
||||||
|
first_main_file := files_from_main_module[0]
|
||||||
|
first_main_file.stmts << ast.FnDecl{
|
||||||
|
name: 'main.main'
|
||||||
|
mod: 'main'
|
||||||
|
file: first_main_file.path
|
||||||
|
return_type: table.void_type
|
||||||
|
}
|
||||||
|
has_main_fn = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure fn main is defined in non lib builds
|
// Make sure fn main is defined in non lib builds
|
||||||
if c.pref.build_mode == .build_module || c.pref.is_test {
|
if c.pref.build_mode == .build_module || c.pref.is_test {
|
||||||
return
|
return
|
||||||
|
@ -159,7 +177,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
if stmt.name == 'main' {
|
if stmt.name == 'main.main' {
|
||||||
has_main_fn = true
|
has_main_fn = true
|
||||||
if stmt.is_pub {
|
if stmt.is_pub {
|
||||||
c.error('function `main` cannot be declared public', stmt.pos)
|
c.error('function `main` cannot be declared public', stmt.pos)
|
||||||
|
@ -214,7 +232,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) check_valid_snake_case(name, identifier string, pos token.Position) {
|
fn (mut c Checker) check_valid_snake_case(name, identifier string, pos token.Position) {
|
||||||
if name[0] == `_` && !c.pref.is_vweb {
|
if !c.pref.is_vweb && ( name[0] == `_` || name.contains('._') ) {
|
||||||
c.error('$identifier `$name` cannot start with `_`', pos)
|
c.error('$identifier `$name` cannot start with `_`', pos)
|
||||||
}
|
}
|
||||||
if util.contains_capital(name) {
|
if util.contains_capital(name) {
|
||||||
|
@ -231,8 +249,8 @@ fn stripped_name(name string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) check_valid_pascal_case(name, identifier string, pos token.Position) {
|
fn (mut c Checker) check_valid_pascal_case(name, identifier string, pos token.Position) {
|
||||||
stripped_name := stripped_name(name)
|
sname := stripped_name(name)
|
||||||
if !stripped_name[0].is_capital() {
|
if !sname[0].is_capital() {
|
||||||
c.error('$identifier `$name` must begin with capital letter', pos)
|
c.error('$identifier `$name` must begin with capital letter', pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -945,7 +963,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
if call_expr.generic_type.has_flag(.generic) {
|
if call_expr.generic_type.has_flag(.generic) {
|
||||||
if c.mod != '' && c.mod != 'main' {
|
if c.mod != '' {
|
||||||
// Need to prepend the module when adding a generic type to a function
|
// Need to prepend the module when adding a generic type to a function
|
||||||
// `fn_gen_types['mymod.myfn'] == ['string', 'int']`
|
// `fn_gen_types['mymod.myfn'] == ['string', 'int']`
|
||||||
c.table.register_fn_gen_type(c.mod + '.' + fn_name, c.cur_generic_type)
|
c.table.register_fn_gen_type(c.mod + '.' + fn_name, c.cur_generic_type)
|
||||||
|
@ -975,12 +993,12 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||||
call_expr.return_type = ret_type
|
call_expr.return_type = ret_type
|
||||||
return ret_type
|
return ret_type
|
||||||
}
|
}
|
||||||
// look for function in format `mod.fn` or `fn` (main/builtin)
|
// look for function in format `mod.fn` or `fn` (builtin)
|
||||||
mut f := table.Fn{}
|
mut f := table.Fn{}
|
||||||
mut found := false
|
mut found := false
|
||||||
mut found_in_args := false
|
mut found_in_args := false
|
||||||
// try prefix with current module as it would have never gotten prefixed
|
// try prefix with current module as it would have never gotten prefixed
|
||||||
if !fn_name.contains('.') && call_expr.mod !in ['builtin', 'main'] {
|
if !fn_name.contains('.') && call_expr.mod !in ['builtin'] {
|
||||||
name_prefixed := '${call_expr.mod}.$fn_name'
|
name_prefixed := '${call_expr.mod}.$fn_name'
|
||||||
if f1 := c.table.find_fn(name_prefixed) {
|
if f1 := c.table.find_fn(name_prefixed) {
|
||||||
call_expr.name = name_prefixed
|
call_expr.name = name_prefixed
|
||||||
|
@ -1014,7 +1032,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||||
c.error('unknown function: $fn_name', call_expr.pos)
|
c.error('unknown function: $fn_name', call_expr.pos)
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
if !found_in_args && call_expr.mod in ['builtin', 'main'] {
|
if !found_in_args {
|
||||||
scope := c.file.scope.innermost(call_expr.pos.pos)
|
scope := c.file.scope.innermost(call_expr.pos.pos)
|
||||||
if _ := scope.find_var(fn_name) {
|
if _ := scope.find_var(fn_name) {
|
||||||
c.error('ambiguous call to: `$fn_name`, may refer to fn `$fn_name` or variable `$fn_name`',
|
c.error('ambiguous call to: `$fn_name`, may refer to fn `$fn_name` or variable `$fn_name`',
|
||||||
|
@ -1219,7 +1237,7 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t
|
||||||
|
|
||||||
pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type) {
|
pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type) {
|
||||||
if or_expr.kind == .propagate {
|
if or_expr.kind == .propagate {
|
||||||
if !c.cur_fn.return_type.has_flag(.optional) && c.cur_fn.name != 'main' {
|
if !c.cur_fn.return_type.has_flag(.optional) && c.cur_fn.name != 'main.main' {
|
||||||
c.error('to propagate the optional call, `$c.cur_fn.name` must itself return an optional',
|
c.error('to propagate the optional call, `$c.cur_fn.name` must itself return an optional',
|
||||||
or_expr.pos)
|
or_expr.pos)
|
||||||
}
|
}
|
||||||
|
@ -1669,7 +1687,7 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
|
||||||
// scope.find(it.name) or {
|
// scope.find(it.name) or {
|
||||||
// c.error('undefined ident: `$it.name`', array_init.pos)
|
// c.error('undefined ident: `$it.name`', array_init.pos)
|
||||||
// }
|
// }
|
||||||
mut full_const_name := if it.mod == 'main' { it.name } else { it.mod + '.' + it.name }
|
mut full_const_name := it.mod + '.' + it.name
|
||||||
if obj := c.file.global_scope.find_const(full_const_name) {
|
if obj := c.file.global_scope.find_const(full_const_name) {
|
||||||
if cint := const_int_value(obj) {
|
if cint := const_int_value(obj) {
|
||||||
fixed_size = cint
|
fixed_size = cint
|
||||||
|
@ -2177,7 +2195,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
// TODO: move this
|
// TODO: move this
|
||||||
if c.const_deps.len > 0 {
|
if c.const_deps.len > 0 {
|
||||||
mut name := ident.name
|
mut name := ident.name
|
||||||
if !name.contains('.') && ident.mod !in ['builtin', 'main'] {
|
if !name.contains('.') && ident.mod !in ['builtin'] {
|
||||||
name = '${ident.mod}.$ident.name'
|
name = '${ident.mod}.$ident.name'
|
||||||
}
|
}
|
||||||
if name == c.const_decl {
|
if name == c.const_decl {
|
||||||
|
@ -2255,7 +2273,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
}
|
}
|
||||||
// prepend mod to look for fn call or const
|
// prepend mod to look for fn call or const
|
||||||
mut name := ident.name
|
mut name := ident.name
|
||||||
if !name.contains('.') && ident.mod !in ['builtin', 'main'] {
|
if !name.contains('.') && ident.mod !in ['builtin'] {
|
||||||
name = '${ident.mod}.$ident.name'
|
name = '${ident.mod}.$ident.name'
|
||||||
}
|
}
|
||||||
if obj := c.file.global_scope.find(name) {
|
if obj := c.file.global_scope.find(name) {
|
||||||
|
@ -2297,6 +2315,17 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
return field.typ
|
return field.typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ident.kind == .unresolved && ident.mod != 'builtin' {
|
||||||
|
// search in the `builtin` idents, for example
|
||||||
|
// main.compare_f32 may actually be builtin.compare_f32
|
||||||
|
saved_mod := ident.mod
|
||||||
|
ident.mod = 'builtin'
|
||||||
|
builtin_type := c.ident( ident )
|
||||||
|
if builtin_type != table.void_type {
|
||||||
|
return builtin_type
|
||||||
|
}
|
||||||
|
ident.mod = saved_mod
|
||||||
|
}
|
||||||
c.error('undefined ident: `$ident.name`', ident.pos)
|
c.error('undefined ident: `$ident.name`', ident.pos)
|
||||||
}
|
}
|
||||||
if c.table.known_type(ident.name) {
|
if c.table.known_type(ident.name) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import v.ast
|
||||||
import v.table
|
import v.table
|
||||||
import v.token
|
import v.token
|
||||||
import strings
|
import strings
|
||||||
|
import v.util
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t',
|
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t',
|
||||||
|
@ -441,10 +442,10 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||||
f.writeln(' {')
|
f.writeln(' {')
|
||||||
match it.kind as k {
|
match it.kind as k {
|
||||||
.insert {
|
.insert {
|
||||||
f.writeln('\tinsert $it.object_var_name into $it.table_name')
|
f.writeln('\tinsert $it.object_var_name into ${util.strip_mod_name(it.table_name)}')
|
||||||
}
|
}
|
||||||
.update {
|
.update {
|
||||||
f.write('\tupdate $it.table_name set ')
|
f.write('\tupdate ${util.strip_mod_name(it.table_name)} set ')
|
||||||
for i, col in it.updated_columns {
|
for i, col in it.updated_columns {
|
||||||
f.write('$col = ')
|
f.write('$col = ')
|
||||||
f.expr(it.update_exprs[i])
|
f.expr(it.update_exprs[i])
|
||||||
|
@ -888,6 +889,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
||||||
f.write(node.field_name)
|
f.write(node.field_name)
|
||||||
}
|
}
|
||||||
ast.SizeOf {
|
ast.SizeOf {
|
||||||
|
if node.is_type {
|
||||||
f.write('sizeof(')
|
f.write('sizeof(')
|
||||||
if node.type_name != '' {
|
if node.type_name != '' {
|
||||||
f.write(node.type_name)
|
f.write(node.type_name)
|
||||||
|
@ -895,6 +897,11 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
||||||
f.write(f.type_to_str(node.typ))
|
f.write(f.type_to_str(node.typ))
|
||||||
}
|
}
|
||||||
f.write(')')
|
f.write(')')
|
||||||
|
} else {
|
||||||
|
f.write('sizeof(')
|
||||||
|
f.expr(node.expr)
|
||||||
|
f.write(')')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.SqlExpr {
|
ast.SqlExpr {
|
||||||
// sql app.db { select from Contributor where repo == id && user == 0 }
|
// sql app.db { select from Contributor where repo == id && user == 0 }
|
||||||
|
@ -918,7 +925,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
||||||
f.write(' ')
|
f.write(' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.write('from $node.table_name')
|
f.write('from ${util.strip_mod_name(node.table_name)}')
|
||||||
f.write(' ')
|
f.write(' ')
|
||||||
if node.has_where {
|
if node.has_where {
|
||||||
f.write('where ')
|
f.write('where ')
|
||||||
|
|
|
@ -83,7 +83,6 @@ mut:
|
||||||
attrs []string // attributes before next decl stmt
|
attrs []string // attributes before next decl stmt
|
||||||
is_builtin_mod bool
|
is_builtin_mod bool
|
||||||
hotcode_fn_names []string
|
hotcode_fn_names []string
|
||||||
fn_main &ast.FnDecl // the FnDecl of the main function. Needed in order to generate the main function code *last*
|
|
||||||
cur_fn &ast.FnDecl = 0
|
cur_fn &ast.FnDecl = 0
|
||||||
cur_generic_type table.Type // `int`, `string`, etc in `foo<T>()`
|
cur_generic_type table.Type // `int`, `string`, etc in `foo<T>()`
|
||||||
sql_i int
|
sql_i int
|
||||||
|
@ -93,6 +92,7 @@ mut:
|
||||||
inside_return bool
|
inside_return bool
|
||||||
strs_to_free string
|
strs_to_free string
|
||||||
inside_call bool
|
inside_call bool
|
||||||
|
has_main bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -126,8 +126,6 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
table: table
|
table: table
|
||||||
pref: pref
|
pref: pref
|
||||||
fn_decl: 0
|
fn_decl: 0
|
||||||
fn_main: 0
|
|
||||||
cur_fn: 0
|
|
||||||
autofree: true
|
autofree: true
|
||||||
indent: -1
|
indent: -1
|
||||||
module_built: pref.path.after('vlib/')
|
module_built: pref.path.after('vlib/')
|
||||||
|
@ -285,10 +283,8 @@ pub fn (mut g Gen) finish() {
|
||||||
if g.pref.is_livemain || g.pref.is_liveshared {
|
if g.pref.is_livemain || g.pref.is_liveshared {
|
||||||
g.generate_hotcode_reloader_code()
|
g.generate_hotcode_reloader_code()
|
||||||
}
|
}
|
||||||
if g.fn_main != voidptr(0) {
|
if !g.pref.is_test {
|
||||||
g.out.writeln('')
|
g.gen_c_main()
|
||||||
g.fn_decl = g.fn_main
|
|
||||||
g.gen_fn_decl(g.fn_main)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,12 +297,12 @@ pub fn (mut g Gen) write_typeof_functions() {
|
||||||
tidx := g.table.find_type_idx(typ.name)
|
tidx := g.table.find_type_idx(typ.name)
|
||||||
g.writeln('char * v_typeof_sumtype_${tidx}(int sidx) { /* $typ.name */ ')
|
g.writeln('char * v_typeof_sumtype_${tidx}(int sidx) { /* $typ.name */ ')
|
||||||
g.writeln(' switch(sidx) {')
|
g.writeln(' switch(sidx) {')
|
||||||
g.writeln(' case $tidx: return "$typ.name";')
|
g.writeln(' case $tidx: return "${util.strip_main_name(typ.name)}";')
|
||||||
for v in sum_info.variants {
|
for v in sum_info.variants {
|
||||||
subtype := g.table.get_type_symbol(v)
|
subtype := g.table.get_type_symbol(v)
|
||||||
g.writeln(' case $v: return "$subtype.name";')
|
g.writeln(' case $v: return "${util.strip_main_name(subtype.name)}";')
|
||||||
}
|
}
|
||||||
g.writeln(' default: return "unknown $typ.name";')
|
g.writeln(' default: return "unknown ${util.strip_main_name(typ.name)}";')
|
||||||
g.writeln(' }')
|
g.writeln(' }')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
}
|
}
|
||||||
|
@ -383,7 +379,7 @@ fn (mut g Gen) register_optional(t table.Type) string {
|
||||||
g.typedefs2.writeln('typedef struct $styp $styp;')
|
g.typedefs2.writeln('typedef struct $styp $styp;')
|
||||||
g.options.write(g.optional_type_text(styp, base))
|
g.options.write(g.optional_type_text(styp, base))
|
||||||
g.options.writeln(';\n')
|
g.options.writeln(';\n')
|
||||||
g.optionals << styp
|
g.optionals << styp.clone()
|
||||||
}
|
}
|
||||||
return styp
|
return styp
|
||||||
}
|
}
|
||||||
|
@ -392,7 +388,7 @@ fn (mut g Gen) register_optional(t table.Type) string {
|
||||||
// i.e. it's always just Cat, not Cat_ptr:
|
// i.e. it's always just Cat, not Cat_ptr:
|
||||||
fn (g &Gen) cc_type(t table.Type) string {
|
fn (g &Gen) cc_type(t table.Type) string {
|
||||||
sym := g.table.get_type_symbol(g.unwrap_generic(t))
|
sym := g.table.get_type_symbol(g.unwrap_generic(t))
|
||||||
mut styp := sym.name.replace('.', '__')
|
mut styp := util.no_dots(sym.name)
|
||||||
if sym.kind == .struct_ {
|
if sym.kind == .struct_ {
|
||||||
info := sym.info as table.Struct
|
info := sym.info as table.Struct
|
||||||
if info.generic_types.len > 0 {
|
if info.generic_types.len > 0 {
|
||||||
|
@ -436,21 +432,20 @@ typedef struct {
|
||||||
match typ.kind {
|
match typ.kind {
|
||||||
.alias {
|
.alias {
|
||||||
parent := &g.table.types[typ.parent_idx]
|
parent := &g.table.types[typ.parent_idx]
|
||||||
styp := typ.name.replace('.', '__')
|
styp := util.no_dots(typ.name)
|
||||||
is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.`
|
is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.`
|
||||||
parent_styp := if is_c_parent { 'struct ' + parent.name[2..].replace('.', '__') } else { parent.name.replace('.',
|
parent_styp := if is_c_parent { 'struct ' + util.no_dots(parent.name[2..]) } else { util.no_dots(parent.name) }
|
||||||
'__') }
|
|
||||||
g.type_definitions.writeln('typedef $parent_styp $styp;')
|
g.type_definitions.writeln('typedef $parent_styp $styp;')
|
||||||
}
|
}
|
||||||
.array {
|
.array {
|
||||||
styp := typ.name.replace('.', '__')
|
styp := util.no_dots(typ.name)
|
||||||
g.type_definitions.writeln('typedef array $styp;')
|
g.type_definitions.writeln('typedef array $styp;')
|
||||||
}
|
}
|
||||||
.interface_ {
|
.interface_ {
|
||||||
g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};')
|
g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};')
|
||||||
}
|
}
|
||||||
.map {
|
.map {
|
||||||
styp := typ.name.replace('.', '__')
|
styp := util.no_dots(typ.name)
|
||||||
g.type_definitions.writeln('typedef map $styp;')
|
g.type_definitions.writeln('typedef map $styp;')
|
||||||
}
|
}
|
||||||
.function {
|
.function {
|
||||||
|
@ -462,7 +457,7 @@ typedef struct {
|
||||||
not_anon := !info.is_anon
|
not_anon := !info.is_anon
|
||||||
if !info.has_decl && !is_multi && (not_anon || is_fn_sig) {
|
if !info.has_decl && !is_multi && (not_anon || is_fn_sig) {
|
||||||
fn_name := if func.language == .c {
|
fn_name := if func.language == .c {
|
||||||
func.name.replace('.', '__')
|
util.no_dots(func.name)
|
||||||
} else if info.is_anon {
|
} else if info.is_anon {
|
||||||
typ.name
|
typ.name
|
||||||
} else {
|
} else {
|
||||||
|
@ -492,7 +487,7 @@ pub fn (mut g Gen) write_multi_return_types() {
|
||||||
if typ.kind != .multi_return {
|
if typ.kind != .multi_return {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
name := typ.name.replace('.', '__')
|
name := util.no_dots(typ.name)
|
||||||
info := typ.info as table.MultiReturn
|
info := typ.info as table.MultiReturn
|
||||||
g.type_definitions.writeln('typedef struct {')
|
g.type_definitions.writeln('typedef struct {')
|
||||||
// TODO copy pasta StructDecl
|
// TODO copy pasta StructDecl
|
||||||
|
@ -643,7 +638,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
g.defer_stmts << defer_stmt
|
g.defer_stmts << defer_stmt
|
||||||
}
|
}
|
||||||
ast.EnumDecl {
|
ast.EnumDecl {
|
||||||
enum_name := node.name.replace('.', '__')
|
enum_name := util.no_dots(node.name)
|
||||||
g.enum_typedefs.writeln('typedef enum {')
|
g.enum_typedefs.writeln('typedef enum {')
|
||||||
mut cur_enum_expr := ''
|
mut cur_enum_expr := ''
|
||||||
mut cur_enum_offset := 0
|
mut cur_enum_offset := 0
|
||||||
|
@ -689,11 +684,10 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keep_fn_decl := g.fn_decl
|
keep_fn_decl := g.fn_decl
|
||||||
g.fn_decl = node // &it
|
g.fn_decl = node
|
||||||
if node.name == 'main' {
|
if node.name == 'main.main' {
|
||||||
// just remember `it`; main code will be generated in finish()
|
g.has_main = true
|
||||||
g.fn_main = node
|
}
|
||||||
} else {
|
|
||||||
if node.name == 'backtrace' ||
|
if node.name == 'backtrace' ||
|
||||||
node.name == 'backtrace_symbols' ||
|
node.name == 'backtrace_symbols' ||
|
||||||
node.name == 'backtrace_symbols_fd' {
|
node.name == 'backtrace_symbols_fd' {
|
||||||
|
@ -705,7 +699,6 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
node.name == 'backtrace_symbols_fd' {
|
node.name == 'backtrace_symbols_fd' {
|
||||||
g.write('\n#endif\n')
|
g.write('\n#endif\n')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
g.fn_decl = keep_fn_decl
|
g.fn_decl = keep_fn_decl
|
||||||
if skip {
|
if skip {
|
||||||
g.out.go_back_to(pos)
|
g.out.go_back_to(pos)
|
||||||
|
@ -786,7 +779,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
g.sql_stmt(node)
|
g.sql_stmt(node)
|
||||||
}
|
}
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
name := if node.language == .c { node.name.replace('.', '__') } else { c_name(node.name) }
|
name := if node.language == .c { util.no_dots(node.name) } else { c_name(node.name) }
|
||||||
// g.writeln('typedef struct {')
|
// g.writeln('typedef struct {')
|
||||||
// for field in it.fields {
|
// for field in it.fields {
|
||||||
// field_type_sym := g.table.get_type_symbol(field.typ)
|
// field_type_sym := g.table.get_type_symbol(field.typ)
|
||||||
|
@ -967,11 +960,11 @@ fn (mut g Gen) gen_assert_stmt(a ast.AssertStmt) {
|
||||||
g.writeln('{')
|
g.writeln('{')
|
||||||
g.writeln(' g_test_oks++;')
|
g.writeln(' g_test_oks++;')
|
||||||
metaname_ok := g.gen_assert_metainfo(a)
|
metaname_ok := g.gen_assert_metainfo(a)
|
||||||
g.writeln(' cb_assertion_ok(&$metaname_ok);')
|
g.writeln(' main__cb_assertion_ok(&$metaname_ok);')
|
||||||
g.writeln('} else {')
|
g.writeln('} else {')
|
||||||
g.writeln(' g_test_fails++;')
|
g.writeln(' g_test_fails++;')
|
||||||
metaname_fail := g.gen_assert_metainfo(a)
|
metaname_fail := g.gen_assert_metainfo(a)
|
||||||
g.writeln(' cb_assertion_failed(&$metaname_fail);')
|
g.writeln(' main__cb_assertion_failed(&$metaname_fail);')
|
||||||
g.writeln(' longjmp(g_jump_buffer, 1);')
|
g.writeln(' longjmp(g_jump_buffer, 1);')
|
||||||
g.writeln(' // TODO')
|
g.writeln(' // TODO')
|
||||||
g.writeln(' // Maybe print all vars in a test function if it fails?')
|
g.writeln(' // Maybe print all vars in a test function if it fails?')
|
||||||
|
@ -1605,7 +1598,11 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
// Only used in IndexExpr
|
// Only used in IndexExpr
|
||||||
}
|
}
|
||||||
ast.SizeOf {
|
ast.SizeOf {
|
||||||
|
if node.is_type {
|
||||||
mut styp := node.type_name
|
mut styp := node.type_name
|
||||||
|
if styp.starts_with('C.') {
|
||||||
|
styp = styp[2..]
|
||||||
|
}
|
||||||
if node.type_name == '' {
|
if node.type_name == '' {
|
||||||
styp = g.typ(node.typ)
|
styp = g.typ(node.typ)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1617,12 +1614,12 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
g.write('/*SizeOfType*/ sizeof(${util.no_dots(styp)})')
|
||||||
if styp.starts_with('C__') {
|
} else {
|
||||||
styp = styp[3..]
|
g.write('/*SizeOfVar*/ sizeof(')
|
||||||
|
g.expr(node.expr)
|
||||||
|
g.write(')')
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
g.write('sizeof($styp)')
|
|
||||||
}
|
}
|
||||||
ast.SqlExpr {
|
ast.SqlExpr {
|
||||||
g.sql_select_expr(node)
|
g.sql_select_expr(node)
|
||||||
|
@ -1685,7 +1682,7 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
||||||
} else if sym.kind == .array_fixed {
|
} else if sym.kind == .array_fixed {
|
||||||
fixed_info := sym.info as table.ArrayFixed
|
fixed_info := sym.info as table.ArrayFixed
|
||||||
typ_name := g.table.get_type_name(fixed_info.elem_type)
|
typ_name := g.table.get_type_name(fixed_info.elem_type)
|
||||||
g.write('tos_lit("[$fixed_info.size]$typ_name")')
|
g.write('tos_lit("[$fixed_info.size]${util.strip_main_name(typ_name)}")')
|
||||||
} else if sym.kind == .function {
|
} else if sym.kind == .function {
|
||||||
info := sym.info as table.FnType
|
info := sym.info as table.FnType
|
||||||
fn_info := info.func
|
fn_info := info.func
|
||||||
|
@ -1694,15 +1691,15 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
repr += ', '
|
repr += ', '
|
||||||
}
|
}
|
||||||
repr += g.table.get_type_name(arg.typ)
|
repr += util.strip_main_name(g.table.get_type_name(arg.typ))
|
||||||
}
|
}
|
||||||
repr += ')'
|
repr += ')'
|
||||||
if fn_info.return_type != table.void_type {
|
if fn_info.return_type != table.void_type {
|
||||||
repr += ' ${g.table.get_type_name(fn_info.return_type)}'
|
repr += ' ${util.strip_main_name(g.table.get_type_name(fn_info.return_type))}'
|
||||||
}
|
}
|
||||||
g.write('tos_lit("$repr")')
|
g.write('tos_lit("$repr")')
|
||||||
} else {
|
} else {
|
||||||
g.write('tos_lit("$sym.name")')
|
g.write('tos_lit("${util.strip_main_name(sym.name)}")')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2039,7 +2036,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if node.name.starts_with('C.') {
|
if node.name.starts_with('C.') {
|
||||||
g.write(node.name[2..].replace('.', '__'))
|
g.write(util.no_dots(node.name[2..]))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if node.kind == .constant { // && !node.name.starts_with('g_') {
|
if node.kind == .constant { // && !node.name.starts_with('g_') {
|
||||||
|
@ -2308,10 +2305,6 @@ fn (g Gen) expr_is_multi_return_call(expr ast.Expr) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) return_statement(node ast.Return) {
|
fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
if g.fn_decl.name == 'main' {
|
|
||||||
g.writeln('return 0;')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if node.exprs.len > 0 {
|
if node.exprs.len > 0 {
|
||||||
// skip `retun $vweb.html()`
|
// skip `retun $vweb.html()`
|
||||||
if node.exprs[0] is ast.ComptimeCall {
|
if node.exprs[0] is ast.ComptimeCall {
|
||||||
|
@ -2772,7 +2765,7 @@ fn (mut g Gen) write_init_function() {
|
||||||
for mod_name in g.table.imports {
|
for mod_name in g.table.imports {
|
||||||
init_fn_name := '${mod_name}.init'
|
init_fn_name := '${mod_name}.init'
|
||||||
if _ := g.table.find_fn(init_fn_name) {
|
if _ := g.table.find_fn(init_fn_name) {
|
||||||
mod_c_name := mod_name.replace('.', '__')
|
mod_c_name := util.no_dots(mod_name)
|
||||||
init_fn_c_name := '${mod_c_name}__init'
|
init_fn_c_name := '${mod_c_name}__init'
|
||||||
g.writeln('\t${init_fn_c_name}();')
|
g.writeln('\t${init_fn_c_name}();')
|
||||||
}
|
}
|
||||||
|
@ -2832,7 +2825,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// sym := g.table.get_type_symbol(typ)
|
// sym := g.table.get_type_symbol(typ)
|
||||||
mut name := typ.name.replace('.', '__')
|
mut name := util.no_dots(typ.name)
|
||||||
match typ.info as info {
|
match typ.info as info {
|
||||||
table.Struct {
|
table.Struct {
|
||||||
if info.generic_types.len > 0 {
|
if info.generic_types.len > 0 {
|
||||||
|
@ -2896,7 +2889,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
||||||
}
|
}
|
||||||
table.ArrayFixed {
|
table.ArrayFixed {
|
||||||
// .array_fixed {
|
// .array_fixed {
|
||||||
styp := typ.name.replace('.', '__')
|
styp := util.no_dots(typ.name)
|
||||||
// array_fixed_char_300 => char x[300]
|
// array_fixed_char_300 => char x[300]
|
||||||
mut fixed := styp[12..]
|
mut fixed := styp[12..]
|
||||||
len := styp.after('_')
|
len := styp.after('_')
|
||||||
|
@ -3073,12 +3066,12 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
if it.kind == .function {
|
if it.kind == .function {
|
||||||
g.write('${it.name}(it)')
|
g.write('${c_name(it.name)}(it)')
|
||||||
} else if it.kind == .variable {
|
} else if it.kind == .variable {
|
||||||
var_info := it.var_info()
|
var_info := it.var_info()
|
||||||
sym := g.table.get_type_symbol(var_info.typ)
|
sym := g.table.get_type_symbol(var_info.typ)
|
||||||
if sym.kind == .function {
|
if sym.kind == .function {
|
||||||
g.write('${it.name}(it)')
|
g.write('${c_name(it.name)}(it)')
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(node.args[0].expr)
|
||||||
}
|
}
|
||||||
|
@ -3125,12 +3118,12 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
if it.kind == .function {
|
if it.kind == .function {
|
||||||
g.write('${it.name}(it)')
|
g.write('${c_name(it.name)}(it)')
|
||||||
} else if it.kind == .variable {
|
} else if it.kind == .variable {
|
||||||
var_info := it.var_info()
|
var_info := it.var_info()
|
||||||
sym_t := g.table.get_type_symbol(var_info.typ)
|
sym_t := g.table.get_type_symbol(var_info.typ)
|
||||||
if sym_t.kind == .function {
|
if sym_t.kind == .function {
|
||||||
g.write('${it.name}(it)')
|
g.write('${c_name(it.name)}(it)')
|
||||||
} else {
|
} else {
|
||||||
g.expr(node.args[0].expr)
|
g.expr(node.args[0].expr)
|
||||||
}
|
}
|
||||||
|
@ -3283,7 +3276,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
||||||
g.stmts(stmts)
|
g.stmts(stmts)
|
||||||
}
|
}
|
||||||
} else if or_block.kind == .propagate {
|
} else if or_block.kind == .propagate {
|
||||||
if g.file.mod.name == 'main' && g.cur_fn.name == 'main' {
|
if g.file.mod.name == 'main' && g.fn_decl.name == 'main.main' {
|
||||||
// In main(), an `opt()?` call is sugar for `opt() or { panic(err) }`
|
// In main(), an `opt()?` call is sugar for `opt() or { panic(err) }`
|
||||||
if g.pref.is_debug {
|
if g.pref.is_debug {
|
||||||
paline, pafile, pamod, pafn := g.panic_debug_info(or_block.pos)
|
paline, pafile, pamod, pafn := g.panic_debug_info(or_block.pos)
|
||||||
|
@ -3471,7 +3464,7 @@ fn (mut g Gen) comp_if_to_ifdef(name string, is_comptime_optional bool) string {
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
fn c_name(name_ string) string {
|
fn c_name(name_ string) string {
|
||||||
name := name_.replace('.', '__')
|
name := util.no_dots(name_)
|
||||||
if name in c_reserved {
|
if name in c_reserved {
|
||||||
return 'v_$name'
|
return 'v_$name'
|
||||||
}
|
}
|
||||||
|
@ -3482,7 +3475,7 @@ fn (g Gen) type_default(typ table.Type) string {
|
||||||
sym := g.table.get_type_symbol(typ)
|
sym := g.table.get_type_symbol(typ)
|
||||||
if sym.kind == .array {
|
if sym.kind == .array {
|
||||||
elem_sym := g.typ(sym.array_info().elem_type)
|
elem_sym := g.typ(sym.array_info().elem_type)
|
||||||
mut elem_type_str := elem_sym.replace('.', '__')
|
mut elem_type_str := util.no_dots(elem_sym)
|
||||||
if elem_type_str.starts_with('C__') {
|
if elem_type_str.starts_with('C__') {
|
||||||
elem_type_str = elem_type_str[3..]
|
elem_type_str = elem_type_str[3..]
|
||||||
}
|
}
|
||||||
|
@ -3562,21 +3555,21 @@ pub fn (mut g Gen) write_tests_main() {
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
all_tfuncs := g.get_all_test_function_names()
|
all_tfuncs := g.get_all_test_function_names()
|
||||||
if g.pref.is_stats {
|
if g.pref.is_stats {
|
||||||
g.writeln('\tBenchedTests bt = start_testing($all_tfuncs.len, tos_lit("$g.pref.path"));')
|
g.writeln('\tmain__BenchedTests bt = main__start_testing($all_tfuncs.len, tos_lit("$g.pref.path"));')
|
||||||
}
|
}
|
||||||
for t in all_tfuncs {
|
for t in all_tfuncs {
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
if g.pref.is_stats {
|
if g.pref.is_stats {
|
||||||
g.writeln('\tBenchedTests_testing_step_start(&bt, tos_lit("$t"));')
|
g.writeln('\tmain__BenchedTests_testing_step_start(&bt, tos_lit("$t"));')
|
||||||
}
|
}
|
||||||
g.writeln('\tif (!setjmp(g_jump_buffer)) ${t}();')
|
g.writeln('\tif (!setjmp(g_jump_buffer)) ${t}();')
|
||||||
if g.pref.is_stats {
|
if g.pref.is_stats {
|
||||||
g.writeln('\tBenchedTests_testing_step_end(&bt);')
|
g.writeln('\tmain__BenchedTests_testing_step_end(&bt);')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
if g.pref.is_stats {
|
if g.pref.is_stats {
|
||||||
g.writeln('\tBenchedTests_end_testing(&bt);')
|
g.writeln('\tmain__BenchedTests_end_testing(&bt);')
|
||||||
}
|
}
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
if g.autofree {
|
if g.autofree {
|
||||||
|
@ -3628,7 +3621,7 @@ fn (g Gen) get_all_test_function_names() []string {
|
||||||
}
|
}
|
||||||
mut all_tfuncs_c := []string{}
|
mut all_tfuncs_c := []string{}
|
||||||
for f in all_tfuncs {
|
for f in all_tfuncs {
|
||||||
all_tfuncs_c << f.replace('.', '__')
|
all_tfuncs_c << util.no_dots(f)
|
||||||
}
|
}
|
||||||
return all_tfuncs_c
|
return all_tfuncs_c
|
||||||
}
|
}
|
||||||
|
@ -3640,12 +3633,12 @@ fn (g Gen) is_importing_os() bool {
|
||||||
fn (mut g Gen) go_stmt(node ast.GoStmt) {
|
fn (mut g Gen) go_stmt(node ast.GoStmt) {
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
expr := node.call_expr as ast.CallExpr
|
expr := node.call_expr as ast.CallExpr
|
||||||
mut name := expr.name // .replace('.', '__')
|
mut name := expr.name // util.no_dots(expr.name)
|
||||||
if expr.is_method {
|
if expr.is_method {
|
||||||
receiver_sym := g.table.get_type_symbol(expr.receiver_type)
|
receiver_sym := g.table.get_type_symbol(expr.receiver_type)
|
||||||
name = receiver_sym.name + '_' + name
|
name = receiver_sym.name + '_' + name
|
||||||
}
|
}
|
||||||
name = name.replace('.', '__')
|
name = util.no_dots(name)
|
||||||
g.writeln('// go')
|
g.writeln('// go')
|
||||||
wrapper_struct_name := 'thread_arg_' + name
|
wrapper_struct_name := 'thread_arg_' + name
|
||||||
wrapper_fn_name := name + '_thread_wrapper'
|
wrapper_fn_name := name + '_thread_wrapper'
|
||||||
|
@ -3750,7 +3743,7 @@ fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
||||||
// `_Animal_Dog_index`
|
// `_Animal_Dog_index`
|
||||||
sub_type := node.right as ast.Type
|
sub_type := node.right as ast.Type
|
||||||
sub_sym := g.table.get_type_symbol(sub_type.typ)
|
sub_sym := g.table.get_type_symbol(sub_type.typ)
|
||||||
g.write('_${sym.name}_${sub_sym.name}_index')
|
g.write('_${c_name(sym.name)}_${c_name(sub_sym.name)}_index')
|
||||||
return
|
return
|
||||||
} else if sym.kind == .sum_type {
|
} else if sym.kind == .sum_type {
|
||||||
g.write('typ $eq ')
|
g.write('typ $eq ')
|
||||||
|
@ -3859,7 +3852,7 @@ fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp, str_fn_name string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_str_for_enum(info table.Enum, styp, str_fn_name string) {
|
fn (mut g Gen) gen_str_for_enum(info table.Enum, styp, str_fn_name string) {
|
||||||
s := styp.replace('.', '__')
|
s := util.no_dots(styp)
|
||||||
g.type_definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
g.type_definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
||||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { /* gen_str_for_enum */')
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { /* gen_str_for_enum */')
|
||||||
g.auto_str_funcs.writeln('\tswitch(it) {')
|
g.auto_str_funcs.writeln('\tswitch(it) {')
|
||||||
|
@ -3896,6 +3889,7 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp, str_fn_name string) {
|
||||||
deref_typ := styp
|
deref_typ := styp
|
||||||
g.auto_str_funcs.writeln('\t$deref_typ *it = &x;')
|
g.auto_str_funcs.writeln('\t$deref_typ *it = &x;')
|
||||||
}
|
}
|
||||||
|
clean_struct_v_type_name = util.strip_main_name(clean_struct_v_type_name)
|
||||||
// generate ident / indent length = 4 spaces
|
// generate ident / indent length = 4 spaces
|
||||||
g.auto_str_funcs.writeln('\tstring indents = tos_lit("");')
|
g.auto_str_funcs.writeln('\tstring indents = tos_lit("");')
|
||||||
g.auto_str_funcs.writeln('\tfor (int i = 0; i < indent_count; ++i) {')
|
g.auto_str_funcs.writeln('\tfor (int i = 0; i < indent_count; ++i) {')
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
module gen
|
||||||
|
|
||||||
|
pub fn (mut g Gen) gen_c_main() {
|
||||||
|
if !g.has_main {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if g.pref.is_liveshared {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.out.writeln('')
|
||||||
|
g.gen_c_main_header()
|
||||||
|
g.writeln('\tmain__main();')
|
||||||
|
g.gen_c_main_footer()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) gen_c_main_header() {
|
||||||
|
if g.pref.os == .windows {
|
||||||
|
if g.is_gui_app() {
|
||||||
|
// GUI application
|
||||||
|
g.writeln('int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, LPWSTR cmd_line, int show_cmd){')
|
||||||
|
} else {
|
||||||
|
// Console application
|
||||||
|
g.writeln('int wmain(int ___argc, wchar_t* ___argv[], wchar_t* ___envp[]){')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.writeln('int main(int ___argc, char** ___argv){')
|
||||||
|
}
|
||||||
|
if g.pref.os == .windows && g.is_gui_app() {
|
||||||
|
g.writeln('\ttypedef LPWSTR*(WINAPI *cmd_line_to_argv)(LPCWSTR, int*);')
|
||||||
|
g.writeln('\tHMODULE shell32_module = LoadLibrary(L"shell32.dll");')
|
||||||
|
g.writeln('\tcmd_line_to_argv CommandLineToArgvW = (cmd_line_to_argv)GetProcAddress(shell32_module, "CommandLineToArgvW");')
|
||||||
|
g.writeln('\tint ___argc;')
|
||||||
|
g.writeln('\twchar_t** ___argv = CommandLineToArgvW(cmd_line, &___argc);')
|
||||||
|
}
|
||||||
|
g.writeln('\t_vinit();')
|
||||||
|
|
||||||
|
if g.pref.is_prof {
|
||||||
|
g.writeln('')
|
||||||
|
g.writeln('\tatexit(vprint_profile_stats);')
|
||||||
|
g.writeln('')
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.is_importing_os() {
|
||||||
|
if g.autofree {
|
||||||
|
g.writeln('free(_const_os__args.data); // empty, inited in _vinit()')
|
||||||
|
}
|
||||||
|
if g.pref.os == .windows {
|
||||||
|
g.writeln('\t_const_os__args = os__init_os_args_wide(___argc, ___argv);')
|
||||||
|
} else {
|
||||||
|
g.writeln('\t_const_os__args = os__init_os_args(___argc, (byteptr*)___argv);')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.pref.is_livemain {
|
||||||
|
g.generate_hotcode_reloading_main_caller()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut g Gen) gen_c_main_footer() {
|
||||||
|
if g.autofree {
|
||||||
|
g.writeln('\t_vcleanup();')
|
||||||
|
}
|
||||||
|
|
||||||
|
g.writeln('\treturn 0;')
|
||||||
|
g.writeln('}')
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ module gen
|
||||||
|
|
||||||
import v.ast
|
import v.ast
|
||||||
import v.table
|
import v.table
|
||||||
|
import v.util
|
||||||
|
|
||||||
fn (g &Gen) comptime_call(node ast.ComptimeCall) {
|
fn (g &Gen) comptime_call(node ast.ComptimeCall) {
|
||||||
if node.is_vweb {
|
if node.is_vweb {
|
||||||
|
@ -12,7 +13,7 @@ fn (g &Gen) comptime_call(node ast.ComptimeCall) {
|
||||||
if stmt is ast.FnDecl {
|
if stmt is ast.FnDecl {
|
||||||
fn_decl := stmt as ast.FnDecl
|
fn_decl := stmt as ast.FnDecl
|
||||||
// insert stmts from vweb_tmpl fn
|
// insert stmts from vweb_tmpl fn
|
||||||
if fn_decl.name.starts_with('vweb_tmpl') {
|
if fn_decl.name.starts_with('main.vweb_tmpl') {
|
||||||
g.inside_vweb_tmpl = true
|
g.inside_vweb_tmpl = true
|
||||||
g.stmts(fn_decl.stmts)
|
g.stmts(fn_decl.stmts)
|
||||||
g.inside_vweb_tmpl = false
|
g.inside_vweb_tmpl = false
|
||||||
|
@ -40,7 +41,7 @@ fn (g &Gen) comptime_call(node ast.ComptimeCall) {
|
||||||
g.write(' else ')
|
g.write(' else ')
|
||||||
}
|
}
|
||||||
g.write('if (string_eq($node.method_name, tos_lit("$method.name"))) ')
|
g.write('if (string_eq($node.method_name, tos_lit("$method.name"))) ')
|
||||||
g.write('${node.sym.name}_${method.name}($amp ')
|
g.write('${util.no_dots(node.sym.name)}_${method.name}($amp ')
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.writeln(');')
|
g.writeln(');')
|
||||||
j++
|
j++
|
||||||
|
@ -66,5 +67,5 @@ fn (mut g Gen) comp_if(it ast.CompIf) {
|
||||||
g.stmts(it.else_stmts)
|
g.stmts(it.else_stmts)
|
||||||
g.defer_ifdef = ''
|
g.defer_ifdef = ''
|
||||||
}
|
}
|
||||||
g.writeln('\n// } $it.val\n#endif\n')
|
g.writeln('\n#endif\n// } $it.val\n')
|
||||||
}
|
}
|
||||||
|
|
100
vlib/v/gen/fn.v
100
vlib/v/gen/fn.v
|
@ -15,12 +15,6 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
// if g.fileis('vweb.v') {
|
// if g.fileis('vweb.v') {
|
||||||
// println('\ngen_fn_decl() $it.name $it.is_generic $g.cur_generic_type')
|
// println('\ngen_fn_decl() $it.name $it.is_generic $g.cur_generic_type')
|
||||||
// }
|
// }
|
||||||
former_cur_fn := g.cur_fn
|
|
||||||
g.cur_fn = &it
|
|
||||||
defer {
|
|
||||||
g.cur_fn = former_cur_fn
|
|
||||||
}
|
|
||||||
is_main := it.name == 'main'
|
|
||||||
if it.is_generic && g.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion
|
if it.is_generic && g.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion
|
||||||
// loop thru each generic type and generate a function
|
// loop thru each generic type and generate a function
|
||||||
for gen_type in g.table.fn_gen_types[it.name] {
|
for gen_type in g.table.fn_gen_types[it.name] {
|
||||||
|
@ -34,9 +28,6 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
g.cur_generic_type = 0
|
g.cur_generic_type = 0
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if is_main && g.pref.is_liveshared {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fn_start_pos := g.out.len
|
fn_start_pos := g.out.len
|
||||||
msvc_attrs := g.write_fn_attrs()
|
msvc_attrs := g.write_fn_attrs()
|
||||||
// Live
|
// Live
|
||||||
|
@ -49,22 +40,6 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
eprintln('INFO: compile with `v -live $g.pref.path `, if you want to use the [live] function $it.name .')
|
eprintln('INFO: compile with `v -live $g.pref.path `, if you want to use the [live] function $it.name .')
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if is_main {
|
|
||||||
if g.pref.os == .windows {
|
|
||||||
if g.is_gui_app() {
|
|
||||||
// GUI application
|
|
||||||
g.writeln('int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance, LPWSTR cmd_line, int show_cmd){')
|
|
||||||
g.last_fn_c_name = 'wWinMain'
|
|
||||||
} else {
|
|
||||||
// Console application
|
|
||||||
g.writeln('int wmain(int ___argc, wchar_t* ___argv[], wchar_t* ___envp[]){')
|
|
||||||
g.last_fn_c_name = 'wmain'
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g.writeln('int main(int ___argc, char** ___argv){')
|
|
||||||
g.last_fn_c_name = it.name
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mut name := it.name
|
mut name := it.name
|
||||||
if name[0] in [`+`, `-`, `*`, `/`, `%`] {
|
if name[0] in [`+`, `-`, `*`, `/`, `%`] {
|
||||||
name = util.replace_op(name)
|
name = util.replace_op(name)
|
||||||
|
@ -73,7 +48,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
name = g.table.get_type_symbol(it.receiver.typ).name + '_' + name
|
name = g.table.get_type_symbol(it.receiver.typ).name + '_' + name
|
||||||
}
|
}
|
||||||
if it.language == .c {
|
if it.language == .c {
|
||||||
name = name.replace('.', '__')
|
name = util.no_dots(name)
|
||||||
} else {
|
} else {
|
||||||
name = c_name(name)
|
name = c_name(name)
|
||||||
}
|
}
|
||||||
|
@ -82,7 +57,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
// foo<T>() => foo_int(), foo_string() etc
|
// foo<T>() => foo_int(), foo_string() etc
|
||||||
gen_name := g.typ(g.cur_generic_type)
|
gen_name := g.typ(g.cur_generic_type)
|
||||||
name += '_' + gen_name
|
name += '_' + gen_name
|
||||||
// type_name = type_name.replace('T', gen_name)
|
type_name = type_name.replace('T', gen_name)
|
||||||
}
|
}
|
||||||
// if g.pref.show_cc && it.is_builtin {
|
// if g.pref.show_cc && it.is_builtin {
|
||||||
// println(name)
|
// println(name)
|
||||||
|
@ -97,7 +72,10 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
if is_livemain {
|
if is_livemain {
|
||||||
g.hotcode_fn_names << name
|
g.hotcode_fn_names << name
|
||||||
}
|
}
|
||||||
mut impl_fn_name := if is_live_wrap { 'impl_live_$name' } else { name }
|
mut impl_fn_name := name
|
||||||
|
if is_live_wrap {
|
||||||
|
impl_fn_name = 'impl_live_${name}'
|
||||||
|
}
|
||||||
g.last_fn_c_name = impl_fn_name
|
g.last_fn_c_name = impl_fn_name
|
||||||
//
|
//
|
||||||
if is_live_wrap {
|
if is_live_wrap {
|
||||||
|
@ -135,16 +113,15 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
// an early exit, which will leave the mutex locked.
|
// an early exit, which will leave the mutex locked.
|
||||||
mut fn_args_list := []string{}
|
mut fn_args_list := []string{}
|
||||||
for ia, fa in fargs {
|
for ia, fa in fargs {
|
||||||
fn_args_list << '${fargtypes[ia]} $fa'
|
fn_args_list << '${fargtypes[ia]} ${fa}'
|
||||||
}
|
}
|
||||||
mut live_fncall := '${impl_fn_name}(' + fargs.join(', ') + ');'
|
mut live_fncall := '${impl_fn_name}(' + fargs.join(', ') + ');'
|
||||||
mut live_fnreturn := ''
|
mut live_fnreturn := ''
|
||||||
if type_name != 'void' {
|
if type_name != 'void' {
|
||||||
live_fncall = '$type_name res = $live_fncall'
|
live_fncall = '${type_name} res = ${live_fncall}'
|
||||||
live_fnreturn = 'return res;'
|
live_fnreturn = 'return res;'
|
||||||
}
|
}
|
||||||
g.definitions.writeln('$type_name ${name}(' + fn_args_list.join(', ') +
|
g.definitions.writeln('$type_name ${name}(' + fn_args_list.join(', ') + ');')
|
||||||
');')
|
|
||||||
g.hotcode_definitions.writeln('$type_name ${name}(' + fn_args_list.join(', ') +
|
g.hotcode_definitions.writeln('$type_name ${name}(' + fn_args_list.join(', ') +
|
||||||
'){')
|
'){')
|
||||||
g.hotcode_definitions.writeln(' pthread_mutex_lock(&live_fn_mutex);')
|
g.hotcode_definitions.writeln(' pthread_mutex_lock(&live_fn_mutex);')
|
||||||
|
@ -153,61 +130,18 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
g.hotcode_definitions.writeln(' $live_fnreturn')
|
g.hotcode_definitions.writeln(' $live_fnreturn')
|
||||||
g.hotcode_definitions.writeln('}')
|
g.hotcode_definitions.writeln('}')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if is_main {
|
|
||||||
if g.pref.os == .windows && g.is_gui_app() {
|
|
||||||
g.writeln('\ttypedef LPWSTR*(WINAPI *cmd_line_to_argv)(LPCWSTR, int*);')
|
|
||||||
g.writeln('\tHMODULE shell32_module = LoadLibrary(L"shell32.dll");')
|
|
||||||
g.writeln('\tcmd_line_to_argv CommandLineToArgvW = (cmd_line_to_argv)GetProcAddress(shell32_module, "CommandLineToArgvW");')
|
|
||||||
g.writeln('\tint ___argc;')
|
|
||||||
g.writeln('\twchar_t** ___argv = CommandLineToArgvW(cmd_line, &___argc);')
|
|
||||||
}
|
|
||||||
g.writeln('\t_vinit();')
|
|
||||||
if g.is_importing_os() {
|
|
||||||
if g.autofree {
|
|
||||||
g.writeln('free(_const_os__args.data); // empty, inited in _vinit()')
|
|
||||||
}
|
|
||||||
if g.pref.os == .windows {
|
|
||||||
g.writeln('\t_const_os__args = os__init_os_args_wide(___argc, ___argv);')
|
|
||||||
}
|
|
||||||
//
|
|
||||||
else {
|
|
||||||
g.writeln('\t_const_os__args = os__init_os_args(___argc, (byteptr*)___argv);')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if g.pref.is_livemain && is_main {
|
|
||||||
g.generate_hotcode_reloading_main_caller()
|
|
||||||
}
|
|
||||||
// Profiling mode? Start counting at the beginning of the function (save current time).
|
// Profiling mode? Start counting at the beginning of the function (save current time).
|
||||||
if g.pref.is_prof {
|
if g.pref.is_prof {
|
||||||
g.profile_fn(it.name, is_main)
|
g.profile_fn(it.name)
|
||||||
}
|
|
||||||
if is_main {
|
|
||||||
g.indent++
|
|
||||||
}
|
}
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
if is_main {
|
|
||||||
g.indent--
|
|
||||||
}
|
|
||||||
// ////////////
|
// ////////////
|
||||||
if is_main {
|
|
||||||
if g.autofree {
|
|
||||||
g.writeln('\t_vcleanup();')
|
|
||||||
}
|
|
||||||
if g.is_test {
|
|
||||||
verror('test files cannot have function `main`')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g.write_defer_stmts_when_needed()
|
g.write_defer_stmts_when_needed()
|
||||||
// /////////
|
// /////////
|
||||||
if g.autofree && !is_main {
|
if g.autofree {
|
||||||
// TODO: remove this, when g.write_autofree_stmts_when_needed works properly
|
// TODO: remove this, when g.write_autofree_stmts_when_needed works properly
|
||||||
g.writeln(g.autofree_scope_vars(it.body_pos.pos))
|
g.writeln(g.autofree_scope_vars(it.body_pos.pos))
|
||||||
}
|
}
|
||||||
if is_main {
|
|
||||||
g.writeln('\treturn 0;')
|
|
||||||
}
|
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
g.defer_stmts = []
|
g.defer_stmts = []
|
||||||
if g.pref.printfn_list.len > 0 && g.last_fn_c_name in g.pref.printfn_list {
|
if g.pref.printfn_list.len > 0 && g.last_fn_c_name in g.pref.printfn_list {
|
||||||
|
@ -249,7 +183,7 @@ fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) ([]string, []string)
|
||||||
caname := c_name(arg.name)
|
caname := c_name(arg.name)
|
||||||
typ := g.unwrap_generic(arg.typ)
|
typ := g.unwrap_generic(arg.typ)
|
||||||
arg_type_sym := g.table.get_type_symbol(typ)
|
arg_type_sym := g.table.get_type_symbol(typ)
|
||||||
mut arg_type_name := g.typ(typ) // arg_type_sym.name.replace('.', '__')
|
mut arg_type_name := g.typ(typ) // util.no_dots(arg_type_sym.name)
|
||||||
// if arg.name == 'xxx' {
|
// if arg.name == 'xxx' {
|
||||||
// println('xxx arg type= ' + arg_type_name)
|
// println('xxx arg type= ' + arg_type_name)
|
||||||
// }
|
// }
|
||||||
|
@ -356,7 +290,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
// mut receiver_type_name := g.cc_type(node.receiver_type)
|
// mut receiver_type_name := g.cc_type(node.receiver_type)
|
||||||
// mut receiver_type_name := g.typ(node.receiver_type)
|
// mut receiver_type_name := g.typ(node.receiver_type)
|
||||||
typ_sym := g.table.get_type_symbol(g.unwrap_generic(node.receiver_type))
|
typ_sym := g.table.get_type_symbol(g.unwrap_generic(node.receiver_type))
|
||||||
mut receiver_type_name := typ_sym.name.replace('.', '__')
|
mut receiver_type_name := util.no_dots(typ_sym.name)
|
||||||
if typ_sym.kind == .interface_ {
|
if typ_sym.kind == .interface_ {
|
||||||
// Speaker_name_table[s._interface_idx].speak(s._object)
|
// Speaker_name_table[s._interface_idx].speak(s._object)
|
||||||
g.write('${c_name(receiver_type_name)}_name_table[')
|
g.write('${c_name(receiver_type_name)}_name_table[')
|
||||||
|
@ -413,7 +347,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.write('*($return_type_str*)')
|
g.write('*($return_type_str*)')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut name := '${receiver_type_name}_$node.name'.replace('.', '__')
|
mut name := util.no_dots('${receiver_type_name}_$node.name')
|
||||||
// Check if expression is: arr[a..b].clone(), arr[a..].clone()
|
// Check if expression is: arr[a..b].clone(), arr[a..].clone()
|
||||||
// if so, then instead of calling array_clone(&array_slice(...))
|
// if so, then instead of calling array_clone(&array_slice(...))
|
||||||
// call array_clone_static(array_slice(...))
|
// call array_clone_static(array_slice(...))
|
||||||
|
@ -424,7 +358,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
if idx is ast.RangeExpr {
|
if idx is ast.RangeExpr {
|
||||||
// expr is arr[range].clone()
|
// expr is arr[range].clone()
|
||||||
// use array_clone_static instead of array_clone
|
// use array_clone_static instead of array_clone
|
||||||
name = '${receiver_type_name}_${node.name}_static'.replace('.', '__')
|
name = util.no_dots('${receiver_type_name}_${node.name}_static')
|
||||||
is_range_slice = true
|
is_range_slice = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,13 +441,13 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
if node.language == .c {
|
if node.language == .c {
|
||||||
// Skip "C."
|
// Skip "C."
|
||||||
g.is_c_call = true
|
g.is_c_call = true
|
||||||
name = name[2..].replace('.', '__')
|
name = util.no_dots(name[2..])
|
||||||
} else {
|
} else {
|
||||||
name = c_name(name)
|
name = c_name(name)
|
||||||
}
|
}
|
||||||
if is_json_encode {
|
if is_json_encode {
|
||||||
// `json__encode` => `json__encode_User`
|
// `json__encode` => `json__encode_User`
|
||||||
name += '_' + json_type_str.replace('.', '__')
|
name += '_' + util.no_dots(json_type_str)
|
||||||
}
|
}
|
||||||
if node.generic_type != table.void_type && node.generic_type != 0 {
|
if node.generic_type != table.void_type && node.generic_type != 0 {
|
||||||
// `foo<int>()` => `foo_int()`
|
// `foo<int>()` => `foo_int()`
|
||||||
|
|
|
@ -1337,8 +1337,8 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
|
fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
|
||||||
// key_typ_sym := g.table.get_type_symbol(it.key_type)
|
// key_typ_sym := g.table.get_type_symbol(it.key_type)
|
||||||
// value_typ_sym := g.table.get_type_symbol(it.value_type)
|
// value_typ_sym := g.table.get_type_symbol(it.value_type)
|
||||||
// key_typ_str := key_typ_sym.name.replace('.', '__')
|
// key_typ_str := util.no_dots(key_typ_sym.name)
|
||||||
// value_typ_str := value_typ_sym.name.replace('.', '__')
|
// value_typ_str := util.no_dots(value_typ_sym.name)
|
||||||
if it.vals.len > 0 {
|
if it.vals.len > 0 {
|
||||||
g.writeln('new Map([')
|
g.writeln('new Map([')
|
||||||
g.inc_indent()
|
g.inc_indent()
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
module gen
|
module gen
|
||||||
|
|
||||||
import v.table
|
import v.table
|
||||||
|
import v.util
|
||||||
import strings
|
import strings
|
||||||
|
|
||||||
// TODO replace with comptime code generation.
|
// TODO replace with comptime code generation.
|
||||||
|
@ -128,12 +129,12 @@ $enc_fn_dec {
|
||||||
|
|
||||||
fn js_enc_name(typ string) string {
|
fn js_enc_name(typ string) string {
|
||||||
name := 'json__encode_$typ'
|
name := 'json__encode_$typ'
|
||||||
return name.replace('.', '__')
|
return util.no_dots(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn js_dec_name(typ string) string {
|
fn js_dec_name(typ string) string {
|
||||||
name := 'json__decode_$typ'
|
name := 'json__decode_$typ'
|
||||||
return name.replace('.', '__')
|
return util.no_dots(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_js_prim(typ string) bool {
|
fn is_js_prim(typ string) bool {
|
||||||
|
|
|
@ -6,12 +6,7 @@ pub struct ProfileCounterMeta{
|
||||||
vpc_calls string
|
vpc_calls string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) profile_fn(fn_name string, is_main bool){
|
fn (mut g Gen) profile_fn(fn_name string){
|
||||||
if is_main {
|
|
||||||
g.writeln('')
|
|
||||||
g.writeln('\tatexit(vprint_profile_stats);')
|
|
||||||
g.writeln('')
|
|
||||||
}
|
|
||||||
if g.pref.profile_no_inline && 'inline' in g.attrs {
|
if g.pref.profile_no_inline && 'inline' in g.attrs {
|
||||||
g.defer_profile_code = ''
|
g.defer_profile_code = ''
|
||||||
return
|
return
|
||||||
|
@ -33,7 +28,7 @@ fn (mut g Gen) profile_fn(fn_name string, is_main bool){
|
||||||
|
|
||||||
pub fn (mut g Gen) gen_vprint_profile_stats() {
|
pub fn (mut g Gen) gen_vprint_profile_stats() {
|
||||||
g.pcs_declarations.writeln('void vprint_profile_stats(){')
|
g.pcs_declarations.writeln('void vprint_profile_stats(){')
|
||||||
fstring := '"%14llu %14.3fms %14.0fns %s \\n"'
|
fstring := '"%14lu %14.3fms %14.0fns %s \\n"'
|
||||||
if g.pref.profile_file == '-' {
|
if g.pref.profile_file == '-' {
|
||||||
for pc_meta in g.pcs {
|
for pc_meta in g.pcs {
|
||||||
g.pcs_declarations.writeln('\tif (${pc_meta.vpc_calls}) printf($fstring, ${pc_meta.vpc_calls}, ${pc_meta.vpc_name}/1000000.0, ${pc_meta.vpc_name}/${pc_meta.vpc_calls}, "${pc_meta.fn_name}" );')
|
g.pcs_declarations.writeln('\tif (${pc_meta.vpc_calls}) printf($fstring, ${pc_meta.vpc_calls}, ${pc_meta.vpc_name}/1000000.0, ${pc_meta.vpc_name}/${pc_meta.vpc_calls}, "${pc_meta.fn_name}" );')
|
||||||
|
|
|
@ -5,6 +5,7 @@ module gen
|
||||||
import v.ast
|
import v.ast
|
||||||
import strings
|
import strings
|
||||||
import v.table
|
import v.table
|
||||||
|
import v.util
|
||||||
|
|
||||||
// pg,mysql etc
|
// pg,mysql etc
|
||||||
const (
|
const (
|
||||||
|
@ -26,16 +27,16 @@ fn (mut g Gen) sql_stmt(node ast.SqlStmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, tos_lit("')
|
g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, tos_lit("')
|
||||||
if node.kind == .insert {
|
if node.kind == .insert {
|
||||||
g.write('insert into `$node.table_name` (')
|
g.write('INSERT INTO `${util.strip_mod_name(node.table_name)}` (')
|
||||||
} else {
|
} else {
|
||||||
g.write('update `$node.table_name` set ')
|
g.write('UPDATE `${util.strip_mod_name(node.table_name)}` SET ')
|
||||||
}
|
}
|
||||||
if node.kind == .insert {
|
if node.kind == .insert {
|
||||||
for i, field in node.fields {
|
for i, field in node.fields {
|
||||||
if field.name == 'id' {
|
if field.name == 'id' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.write(field.name)
|
g.write('`${field.name}`')
|
||||||
if i < node.fields.len - 1 {
|
if i < node.fields.len - 1 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
|
@ -59,7 +60,7 @@ fn (mut g Gen) sql_stmt(node ast.SqlStmt) {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.write(' where ')
|
g.write(' WHERE ')
|
||||||
}
|
}
|
||||||
if node.kind == .update {
|
if node.kind == .update {
|
||||||
g.expr_to_sql(node.where_expr)
|
g.expr_to_sql(node.where_expr)
|
||||||
|
@ -101,24 +102,24 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) {
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
cur_line := g.go_before_stmt(0)
|
cur_line := g.go_before_stmt(0)
|
||||||
mut q := 'select '
|
mut sql_query := 'SELECT '
|
||||||
if node.is_count {
|
if node.is_count {
|
||||||
// `select count(*) from User`
|
// `select count(*) from User`
|
||||||
q += 'count(*) from `$node.table_name`'
|
sql_query += 'COUNT(*) FROM `${util.strip_mod_name(node.table_name)}` '
|
||||||
} else {
|
} else {
|
||||||
// `select id, name, country from User`
|
// `select id, name, country from User`
|
||||||
for i, field in node.fields {
|
for i, field in node.fields {
|
||||||
q += '$field.name'
|
sql_query += '`${field.name}`'
|
||||||
if i < node.fields.len - 1 {
|
if i < node.fields.len - 1 {
|
||||||
q += ', '
|
sql_query += ', '
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
q += ' from `$node.table_name`'
|
sql_query += ' FROM `${util.strip_mod_name(node.table_name)}`'
|
||||||
}
|
}
|
||||||
if node.has_where {
|
if node.has_where {
|
||||||
q += ' where '
|
sql_query += ' WHERE '
|
||||||
}
|
}
|
||||||
// g.write('${dbtype}__DB_q_int(*(${dbtype}__DB*)${node.db_var_name}.data, tos_lit("$q')
|
// g.write('${dbtype}__DB_q_int(*(${dbtype}__DB*)${node.db_var_name}.data, tos_lit("$sql_query')
|
||||||
g.sql_stmt_name = g.new_tmp_var()
|
g.sql_stmt_name = g.new_tmp_var()
|
||||||
db_name := g.new_tmp_var()
|
db_name := g.new_tmp_var()
|
||||||
g.writeln('\n\t// sql select')
|
g.writeln('\n\t// sql select')
|
||||||
|
@ -126,18 +127,19 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) {
|
||||||
g.write('${dbtype}__DB $db_name = ') // $node.db_var_name;')
|
g.write('${dbtype}__DB $db_name = ') // $node.db_var_name;')
|
||||||
g.expr(node.db_expr)
|
g.expr(node.db_expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
// g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt(*(${dbtype}__DB*)${node.db_var_name}.data, tos_lit("$q')
|
// g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt(*(${dbtype}__DB*)${node.db_var_name}.data, tos_lit("$sql_query')
|
||||||
g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, tos_lit("$q')
|
g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, tos_lit("')
|
||||||
|
g.write(sql_query)
|
||||||
if node.has_where && node.where_expr is ast.InfixExpr {
|
if node.has_where && node.where_expr is ast.InfixExpr {
|
||||||
g.expr_to_sql(node.where_expr)
|
g.expr_to_sql(node.where_expr)
|
||||||
}
|
}
|
||||||
g.write(' order by id ')
|
g.write(' ORDER BY id ')
|
||||||
if node.has_limit {
|
if node.has_limit {
|
||||||
g.write(' limit ')
|
g.write(' LIMIT ')
|
||||||
g.expr_to_sql(node.limit_expr)
|
g.expr_to_sql(node.limit_expr)
|
||||||
}
|
}
|
||||||
if node.has_offset {
|
if node.has_offset {
|
||||||
g.write(' offset ')
|
g.write(' OFFSET ')
|
||||||
g.expr_to_sql(node.offset_expr)
|
g.expr_to_sql(node.offset_expr)
|
||||||
}
|
}
|
||||||
g.writeln('"));')
|
g.writeln('"));')
|
||||||
|
|
|
@ -799,7 +799,7 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
|
||||||
fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
||||||
println(term.green('\n$node.name:'))
|
println(term.green('\n$node.name:'))
|
||||||
g.stack_var_pos = 0
|
g.stack_var_pos = 0
|
||||||
is_main := node.name == 'main'
|
is_main := node.name == 'main.main'
|
||||||
// println('saving addr $node.name $g.buf.len.hex2()')
|
// println('saving addr $node.name $g.buf.len.hex2()')
|
||||||
if is_main {
|
if is_main {
|
||||||
g.save_main_fn_addr()
|
g.save_main_fn_addr()
|
||||||
|
|
|
@ -121,7 +121,7 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
||||||
for stmt in file.stmts {
|
for stmt in file.stmts {
|
||||||
if stmt is ast.FnDecl {
|
if stmt is ast.FnDecl {
|
||||||
fn_decl := stmt as ast.FnDecl
|
fn_decl := stmt as ast.FnDecl
|
||||||
if fn_decl.name == 'vweb_tmpl_$p.cur_fn_name' {
|
if fn_decl.name == 'main.vweb_tmpl_${p.cur_fn_name}' {
|
||||||
tmpl_scope := file.scope.innermost(fn_decl.body_pos.pos)
|
tmpl_scope := file.scope.innermost(fn_decl.body_pos.pos)
|
||||||
for _, obj in p.scope.objects {
|
for _, obj in p.scope.objects {
|
||||||
if obj is ast.Var {
|
if obj is ast.Var {
|
||||||
|
|
|
@ -35,7 +35,8 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
|
||||||
// In case of `foo<T>()`
|
// In case of `foo<T>()`
|
||||||
// T is unwrapped and registered in the checker.
|
// T is unwrapped and registered in the checker.
|
||||||
if !generic_type.has_flag(.generic) {
|
if !generic_type.has_flag(.generic) {
|
||||||
p.table.register_fn_gen_type(fn_name, generic_type)
|
full_generic_fn_name := if fn_name.contains('.') { fn_name } else { p.prepend_mod(fn_name) }
|
||||||
|
p.table.register_fn_gen_type(full_generic_fn_name, generic_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
|
@ -237,6 +238,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
is_deprecated: is_deprecated
|
is_deprecated: is_deprecated
|
||||||
ctdefine: ctdefine
|
ctdefine: ctdefine
|
||||||
|
mod: p.mod
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if language == .c {
|
if language == .c {
|
||||||
|
@ -249,6 +251,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
if _ := p.table.find_fn(name) {
|
if _ := p.table.find_fn(name) {
|
||||||
p.fn_redefinition_error(name)
|
p.fn_redefinition_error(name)
|
||||||
}
|
}
|
||||||
|
//p.warn('reg functn $name ()')
|
||||||
p.table.register_fn(table.Fn{
|
p.table.register_fn(table.Fn{
|
||||||
name: name
|
name: name
|
||||||
args: args
|
args: args
|
||||||
|
@ -372,7 +375,8 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool, bool) {
|
||||||
mut args := []table.Arg{}
|
mut args := []table.Arg{}
|
||||||
mut is_variadic := false
|
mut is_variadic := false
|
||||||
// `int, int, string` (no names, just types)
|
// `int, int, string` (no names, just types)
|
||||||
types_only := p.tok.kind in [.amp, .ellipsis, .key_fn] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) ||
|
argname := if p.tok.kind == .name && p.tok.lit.len > 0 && p.tok.lit[0].is_capital() { p.prepend_mod(p.tok.lit) } else { p.tok.lit }
|
||||||
|
types_only := p.tok.kind in [.amp, .ellipsis, .key_fn] || (p.peek_tok.kind == .comma && p.table.known_type(argname)) ||
|
||||||
p.peek_tok.kind == .rpar
|
p.peek_tok.kind == .rpar
|
||||||
// TODO copy pasta, merge 2 branches
|
// TODO copy pasta, merge 2 branches
|
||||||
if types_only {
|
if types_only {
|
||||||
|
@ -500,16 +504,13 @@ fn (mut p Parser) fn_redefinition_error(name string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn have_fn_main(stmts []ast.Stmt) bool {
|
fn have_fn_main(stmts []ast.Stmt) bool {
|
||||||
mut has_main_fn := false
|
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
match stmt {
|
if stmt is ast.FnDecl {
|
||||||
ast.FnDecl {
|
f := stmt as ast.FnDecl
|
||||||
if stmt.name == 'main' {
|
if f.name == 'main.main' && f.mod == 'main' {
|
||||||
has_main_fn = true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {}
|
|
||||||
}
|
}
|
||||||
}
|
return false
|
||||||
return has_main_fn
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ fn (p &Parser) prepend_mod(name string) string {
|
||||||
if p.expr_mod != '' {
|
if p.expr_mod != '' {
|
||||||
return p.expr_mod + '.' + name
|
return p.expr_mod + '.' + name
|
||||||
}
|
}
|
||||||
if p.builtin_mod || p.mod == 'main' {
|
if p.builtin_mod {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
return '${p.mod}.$name'
|
return '${p.mod}.$name'
|
||||||
|
|
|
@ -167,7 +167,7 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr bool) table
|
||||||
name = '${p.imports[name]}.$p.tok.lit'
|
name = '${p.imports[name]}.$p.tok.lit'
|
||||||
} else if p.expr_mod != '' {
|
} else if p.expr_mod != '' {
|
||||||
name = p.expr_mod + '.' + name
|
name = p.expr_mod + '.' + name
|
||||||
} else if p.mod !in ['builtin', 'main'] && name !in table.builtin_type_names && name.len > 1 {
|
} else if p.mod !in ['builtin'] && name !in p.table.type_idxs && name.len > 1 {
|
||||||
// `Foo` in module `mod` means `mod.Foo`
|
// `Foo` in module `mod` means `mod.Foo`
|
||||||
name = p.mod + '.' + name
|
name = p.mod + '.' + name
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,16 +148,7 @@ fn (mut p Parser) parse() ast.File {
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
if p.tok.kind == .eof {
|
if p.tok.kind == .eof {
|
||||||
if p.pref.is_script && !p.pref.is_test && p.mod == 'main' && !have_fn_main(stmts) {
|
|
||||||
stmts << ast.FnDecl{
|
|
||||||
name: 'main'
|
|
||||||
mod: p.mod
|
|
||||||
file: p.file_name
|
|
||||||
return_type: table.void_type
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p.check_unused_imports()
|
p.check_unused_imports()
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// println('stmt at ' + p.tok.str())
|
// println('stmt at ' + p.tok.str())
|
||||||
|
@ -449,8 +440,8 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
|
||||||
stmts << p.stmt(false)
|
stmts << p.stmt(false)
|
||||||
}
|
}
|
||||||
return ast.FnDecl{
|
return ast.FnDecl{
|
||||||
name: 'main'
|
name: 'main.main'
|
||||||
mod: p.mod
|
mod: 'main'
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
file: p.file_name
|
file: p.file_name
|
||||||
return_type: table.void_type
|
return_type: table.void_type
|
||||||
|
@ -845,19 +836,11 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
if p.tok.lit in ['r', 'c', 'js'] && p.peek_tok.kind == .string && !p.inside_str_interp {
|
if p.tok.lit in ['r', 'c', 'js'] && p.peek_tok.kind == .string && !p.inside_str_interp {
|
||||||
return p.string_expr()
|
return p.string_expr()
|
||||||
}
|
}
|
||||||
mut known_var := false
|
known_var := p.mark_var_as_used( p.tok.lit )
|
||||||
if obj := p.scope.find(p.tok.lit) {
|
|
||||||
match mut obj {
|
|
||||||
ast.Var {
|
|
||||||
known_var = true
|
|
||||||
obj.is_used = true
|
|
||||||
}
|
|
||||||
else {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mut is_mod_cast := false
|
mut is_mod_cast := false
|
||||||
if p.peek_tok.kind == .dot && !known_var &&
|
if p.peek_tok.kind == .dot && !known_var &&
|
||||||
(language != .v || p.known_import(p.tok.lit) || p.mod.all_after_last('.') == p.tok.lit) {
|
(language != .v || p.known_import(p.tok.lit) ||
|
||||||
|
p.mod.all_after_last('.') == p.tok.lit) {
|
||||||
if language == .c {
|
if language == .c {
|
||||||
mod = 'C'
|
mod = 'C'
|
||||||
} else if language == .js {
|
} else if language == .js {
|
||||||
|
@ -1490,10 +1473,10 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||||
pubfn := if p.mod == 'main' { 'fn' } else { 'pub fn' }
|
pubfn := if p.mod == 'main' { 'fn' } else { 'pub fn' }
|
||||||
p.scanner.codegen('
|
p.scanner.codegen('
|
||||||
//
|
//
|
||||||
$pubfn ( e &$name) has(flag $name) bool { return (int(*e) & (1 << int(flag))) != 0 }
|
$pubfn ( e &$enum_name) has(flag $enum_name) bool { return (int(*e) & (1 << int(flag))) != 0 }
|
||||||
$pubfn (mut e $name) set(flag $name) { unsafe{ *e = int(*e) | (1 << int(flag)) } }
|
$pubfn (mut e $enum_name) set(flag $enum_name) { unsafe{ *e = int(*e) | (1 << int(flag)) } }
|
||||||
$pubfn (mut e $name) clear(flag $name) { unsafe{ *e = int(*e) & ~(1 << int(flag)) } }
|
$pubfn (mut e $enum_name) clear(flag $enum_name) { unsafe{ *e = int(*e) & ~(1 << int(flag)) } }
|
||||||
$pubfn (mut e $name) toggle(flag $name) { unsafe{ *e = int(*e) ^ (1 << int(flag)) } }
|
$pubfn (mut e $enum_name) toggle(flag $enum_name) { unsafe{ *e = int(*e) ^ (1 << int(flag)) } }
|
||||||
//
|
//
|
||||||
')
|
')
|
||||||
}
|
}
|
||||||
|
@ -1687,3 +1670,16 @@ fn (mut p Parser) rewind_scanner_to_current_token_in_new_mode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut p Parser) mark_var_as_used(varname string) bool {
|
||||||
|
if obj := p.scope.find(varname) {
|
||||||
|
match mut obj {
|
||||||
|
ast.Var {
|
||||||
|
obj.is_used = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -94,19 +94,24 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.key_sizeof {
|
.key_sizeof {
|
||||||
|
pos := p.tok.position()
|
||||||
p.next() // sizeof
|
p.next() // sizeof
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
sizeof_type := p.parse_type()
|
is_known_var := p.mark_var_as_used( p.tok.lit )
|
||||||
if p.tok.lit == 'C' {
|
if is_known_var {
|
||||||
p.next()
|
expr := p.parse_ident(table.Language.v)
|
||||||
p.check(.dot)
|
|
||||||
node = ast.SizeOf{
|
node = ast.SizeOf{
|
||||||
type_name: p.check_name()
|
is_type: false
|
||||||
typ: sizeof_type
|
expr: expr
|
||||||
|
pos: pos
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
sizeof_type := p.parse_type()
|
||||||
node = ast.SizeOf{
|
node = ast.SizeOf{
|
||||||
|
is_type: true
|
||||||
typ: sizeof_type
|
typ: sizeof_type
|
||||||
|
type_name: p.table.get_type_symbol(sizeof_type).name
|
||||||
|
pos: pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
|
|
|
@ -151,7 +151,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
|
||||||
} else if kind == .update {
|
} else if kind == .update {
|
||||||
if !p.pref.is_fmt {
|
if !p.pref.is_fmt {
|
||||||
// NB: in vfmt mode, v parses just a single file and table_name may not have been registered
|
// NB: in vfmt mode, v parses just a single file and table_name may not have been registered
|
||||||
idx := p.table.find_type_idx(table_name)
|
idx := p.table.find_type_idx(p.prepend_mod(table_name))
|
||||||
table_type = table.new_type(idx)
|
table_type = table.new_type(idx)
|
||||||
}
|
}
|
||||||
p.check_sql_keyword('where')
|
p.check_sql_keyword('where')
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
module scanner
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
struct TestStruct {
|
||||||
|
test string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut t TestStruct) test_struct() {
|
||||||
|
assert @STRUCT == 'TestStruct'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut t TestStruct) test_struct_w_return() string {
|
||||||
|
assert @STRUCT == 'TestStruct'
|
||||||
|
return t.test
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut t TestStruct) test_struct_w_high_order(cb fn(int)string) string {
|
||||||
|
assert @STRUCT == 'TestStruct'
|
||||||
|
return 'test'+cb(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestFn { }
|
||||||
|
|
||||||
|
fn (mut t TestFn) tst_1() {
|
||||||
|
assert @FN == 'tst_1'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut t TestFn) tst_2(cb fn(int)) {
|
||||||
|
assert @FN == 'tst_2'
|
||||||
|
cb(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_name_mod_level() {
|
||||||
|
assert @FN == 'fn_name_mod_level'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_name_mod_level_high_order(cb fn(int)) {
|
||||||
|
assert @FN == 'fn_name_mod_level_high_order'
|
||||||
|
cb(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_at_file() {
|
||||||
|
// Test @FILE
|
||||||
|
f := os.file_name( @FILE )
|
||||||
|
assert f == 'scanner_at_literals_test.v'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_at_fn() {
|
||||||
|
// Test @FN
|
||||||
|
assert @FN == 'test_at_fn'
|
||||||
|
|
||||||
|
fn_name_mod_level()
|
||||||
|
fn_name_mod_level_high_order(fn(i int){
|
||||||
|
t := i + 1
|
||||||
|
assert t == 2
|
||||||
|
})
|
||||||
|
|
||||||
|
mut tfn := TestFn{}
|
||||||
|
tfn.tst_1()
|
||||||
|
tfn.tst_2(fn(i int){
|
||||||
|
t := i + 1
|
||||||
|
assert t == 2
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_at_mod() {
|
||||||
|
// Test @MOD
|
||||||
|
assert @MOD == 'scanner'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_at_struct() {
|
||||||
|
// Test @STRUCT
|
||||||
|
assert @STRUCT == ''
|
||||||
|
mut ts := TestStruct { test: "test" }
|
||||||
|
ts.test_struct()
|
||||||
|
r1 := ts.test_struct_w_return()
|
||||||
|
r2 := ts.test_struct_w_high_order(fn(i int)string{
|
||||||
|
assert @STRUCT == ''
|
||||||
|
return i.str()
|
||||||
|
})
|
||||||
|
assert r1 == 'test'
|
||||||
|
assert r2 == 'test2'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_vmod_file() {
|
||||||
|
content := @VMOD_FILE
|
||||||
|
assert content.len > 0
|
||||||
|
assert content.contains('Module {')
|
||||||
|
assert content.contains('name:')
|
||||||
|
assert content.contains('version:')
|
||||||
|
assert content.contains('description:')
|
||||||
|
}
|
|
@ -5,45 +5,6 @@ module scanner
|
||||||
|
|
||||||
import v.token
|
import v.token
|
||||||
|
|
||||||
|
|
||||||
struct TestStruct {
|
|
||||||
test string
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut t TestStruct) test_struct() {
|
|
||||||
assert @STRUCT == 'TestStruct'
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut t TestStruct) test_struct_w_return() string {
|
|
||||||
assert @STRUCT == 'TestStruct'
|
|
||||||
return t.test
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut t TestStruct) test_struct_w_high_order(cb fn(int)string) string {
|
|
||||||
assert @STRUCT == 'TestStruct'
|
|
||||||
return 'test'+cb(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TestFn { }
|
|
||||||
|
|
||||||
fn (mut t TestFn) tst_1() {
|
|
||||||
assert @FN == 'tst_1'
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut t TestFn) tst_2(cb fn(int)) {
|
|
||||||
assert @FN == 'tst_2'
|
|
||||||
cb(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fn_name_mod_level() {
|
|
||||||
assert @FN == 'fn_name_mod_level'
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fn_name_mod_level_high_order(cb fn(int)) {
|
|
||||||
assert @FN == 'fn_name_mod_level_high_order'
|
|
||||||
cb(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scan_kinds(text string) []token.Kind {
|
fn scan_kinds(text string) []token.Kind {
|
||||||
mut scanner := new_scanner(text, .skip_comments, false)
|
mut scanner := new_scanner(text, .skip_comments, false)
|
||||||
mut token_kinds := []token.Kind{}
|
mut token_kinds := []token.Kind{}
|
||||||
|
@ -66,14 +27,18 @@ fn test_scan() {
|
||||||
assert token_kinds[3] == .plus
|
assert token_kinds[3] == .plus
|
||||||
assert token_kinds[4] == .number
|
assert token_kinds[4] == .number
|
||||||
assert token_kinds[5] == .rpar
|
assert token_kinds[5] == .rpar
|
||||||
// test number costants input format
|
}
|
||||||
|
|
||||||
|
fn test_number_constant_input_format() {
|
||||||
mut c := 0xa0
|
mut c := 0xa0
|
||||||
assert c == 0xa0
|
assert c == 0xa0
|
||||||
c = 0b1001
|
c = 0b1001
|
||||||
assert c == 9
|
assert c == 9
|
||||||
c = 1000000
|
c = 1000000
|
||||||
assert c == 1000000
|
assert c == 1000000
|
||||||
// test float conversion and reading
|
}
|
||||||
|
|
||||||
|
fn test_float_conversion_and_reading() {
|
||||||
d := 23000000e-3
|
d := 23000000e-3
|
||||||
assert int(d) == 23000
|
assert int(d) == 23000
|
||||||
mut e := 1.2E3 * -1e-1
|
mut e := 1.2E3 * -1e-1
|
||||||
|
@ -83,92 +48,62 @@ fn test_scan() {
|
||||||
assert 1.23e+10 == 1.23e10
|
assert 1.23e+10 == 1.23e10
|
||||||
assert 1.23e+10 == 1.23e0010
|
assert 1.23e+10 == 1.23e0010
|
||||||
assert (-1.23e+10) == (1.23e0010 * -1.0)
|
assert (-1.23e+10) == (1.23e0010 * -1.0)
|
||||||
|
|
||||||
// Test @FN
|
|
||||||
assert @FN == 'test_scan'
|
|
||||||
|
|
||||||
fn_name_mod_level()
|
|
||||||
fn_name_mod_level_high_order(fn(i int){
|
|
||||||
t := i + 1
|
|
||||||
assert t == 2
|
|
||||||
})
|
|
||||||
|
|
||||||
mut tfn := TestFn{}
|
|
||||||
tfn.tst_1()
|
|
||||||
tfn.tst_2(fn(i int){
|
|
||||||
t := i + 1
|
|
||||||
assert t == 2
|
|
||||||
})
|
|
||||||
|
|
||||||
// Test @MOD
|
|
||||||
assert @MOD == 'scanner'
|
|
||||||
|
|
||||||
// Test @STRUCT
|
|
||||||
assert @STRUCT == ''
|
|
||||||
|
|
||||||
mut ts := TestStruct { test: "test" }
|
|
||||||
ts.test_struct()
|
|
||||||
r1 := ts.test_struct_w_return()
|
|
||||||
r2 := ts.test_struct_w_high_order(fn(i int)string{
|
|
||||||
assert @STRUCT == ''
|
|
||||||
return i.str()
|
|
||||||
})
|
|
||||||
assert r1 == 'test'
|
|
||||||
assert r2 == 'test2'
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_vmod_file() {
|
fn test_reference_bools() {
|
||||||
content := @VMOD_FILE
|
result := scan_kinds('true && false')
|
||||||
assert content.len > 0
|
|
||||||
assert content.contains('Module {')
|
|
||||||
assert content.contains('name:')
|
|
||||||
assert content.contains('version:')
|
|
||||||
assert content.contains('description:')
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_reference() {
|
|
||||||
mut result := scan_kinds('true && false')
|
|
||||||
assert result.len == 3
|
assert result.len == 3
|
||||||
assert result[0] == .key_true
|
assert result[0] == .key_true
|
||||||
assert result[1] == .and
|
assert result[1] == .and
|
||||||
assert result[2] == .key_false
|
assert result[2] == .key_false
|
||||||
|
}
|
||||||
|
|
||||||
result = scan_kinds('&foo')
|
fn test_reference_var() {
|
||||||
|
result := scan_kinds('&foo')
|
||||||
assert result.len == 2
|
assert result.len == 2
|
||||||
assert result[0] == .amp
|
assert result[0] == .amp
|
||||||
assert result[1] == .name
|
assert result[1] == .name
|
||||||
|
}
|
||||||
|
|
||||||
result = scan_kinds('[]&foo')
|
fn test_array_of_references() {
|
||||||
|
result := scan_kinds('[]&foo')
|
||||||
assert result.len == 4
|
assert result.len == 4
|
||||||
assert result[0] == .lsbr
|
assert result[0] == .lsbr
|
||||||
assert result[1] == .rsbr
|
assert result[1] == .rsbr
|
||||||
assert result[2] == .amp
|
assert result[2] == .amp
|
||||||
assert result[3] == .name
|
assert result[3] == .name
|
||||||
|
}
|
||||||
|
|
||||||
result = scan_kinds('&[]&foo')
|
fn test_ref_array_of_references() {
|
||||||
|
result := scan_kinds('&[]&foo')
|
||||||
assert result.len == 5
|
assert result.len == 5
|
||||||
assert result[0] == .amp
|
assert result[0] == .amp
|
||||||
assert result[1] == .lsbr
|
assert result[1] == .lsbr
|
||||||
assert result[2] == .rsbr
|
assert result[2] == .rsbr
|
||||||
assert result[3] == .amp
|
assert result[3] == .amp
|
||||||
assert result[4] == .name
|
assert result[4] == .name
|
||||||
|
}
|
||||||
|
|
||||||
result = scan_kinds('&&foo')
|
fn test_ref_ref_foo() {
|
||||||
|
result := scan_kinds('&&foo')
|
||||||
assert result.len == 3
|
assert result.len == 3
|
||||||
assert result[0] == .amp
|
assert result[0] == .amp
|
||||||
assert result[1] == .amp
|
assert result[1] == .amp
|
||||||
assert result[2] == .name
|
assert result[2] == .name
|
||||||
|
}
|
||||||
|
|
||||||
result = scan_kinds('[]&&foo')
|
fn test_array_of_ref_ref_foo() {
|
||||||
|
result := scan_kinds('[]&&foo')
|
||||||
assert result.len == 5
|
assert result.len == 5
|
||||||
assert result[0] == .lsbr
|
assert result[0] == .lsbr
|
||||||
assert result[1] == .rsbr
|
assert result[1] == .rsbr
|
||||||
assert result[2] == .amp
|
assert result[2] == .amp
|
||||||
assert result[3] == .amp
|
assert result[3] == .amp
|
||||||
assert result[4] == .name
|
assert result[4] == .name
|
||||||
|
}
|
||||||
|
|
||||||
result = scan_kinds('&&[]&&foo')
|
fn test_ref_ref_array_ref_ref_foo() {
|
||||||
|
result := scan_kinds('&&[]&&foo')
|
||||||
assert result.len == 7
|
assert result.len == 7
|
||||||
assert result[0] == .amp
|
assert result[0] == .amp
|
||||||
assert result[1] == .amp
|
assert result[1] == .amp
|
||||||
|
|
|
@ -113,6 +113,7 @@ pub fn (mut t Table) register_fn(new_fn Fn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut t TypeSymbol) register_method(new_fn Fn) {
|
pub fn (mut t TypeSymbol) register_method(new_fn Fn) {
|
||||||
|
// println('reg me $new_fn.name nr_args=$new_fn.args.len')
|
||||||
t.methods << new_fn
|
t.methods << new_fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
This folder contains a V project,
|
||||||
|
intended to be used as a demonstration
|
||||||
|
for how to test functions defined inside
|
||||||
|
a main module.
|
||||||
|
|
||||||
|
See my_test.v and my_other_test.v .
|
||||||
|
These files work as any other internal module tests,
|
||||||
|
i.e. they do `module main` at their top, so that v knows,
|
||||||
|
that they are internal tests, and for which module they apply.
|
||||||
|
|
||||||
|
When you do `v my_test.v`, v will try to find other *.v files in
|
||||||
|
the same folder that also have `module main` at their top,
|
||||||
|
then it will process them and process the my_test.v file too.
|
||||||
|
|
||||||
|
The v `fn main(){}` function that you most likely also have will get
|
||||||
|
compiled as normal to `void main__main(){...}`, but it will NOT be
|
||||||
|
called by anything, so it will not mess up your tests.
|
||||||
|
|
||||||
|
Instead, your test_ functions will get called inside the generated
|
||||||
|
`int main(){...}` test runner, just like it is the case with all _test.v
|
||||||
|
files (internal or external ones).
|
||||||
|
|
||||||
|
NB: each _test.v file is compiled separately from all other _test.v
|
||||||
|
files, so you can have conflicting test_ functions in them without a
|
||||||
|
problem too.
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
fn iadd(x int, y int) int {
|
||||||
|
return x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main(){
|
||||||
|
println('Hello world')
|
||||||
|
println('iadd: ' + iadd(1,2).str())
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
module main
|
||||||
|
fn test_iadd_3_4(){
|
||||||
|
a := iadd(3,4)
|
||||||
|
assert a == 7
|
||||||
|
assert iadd(10,20) == 30
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
module main
|
||||||
|
fn test_iadd_3_4(){
|
||||||
|
a := iadd(3,4)
|
||||||
|
assert a == 7
|
||||||
|
}
|
||||||
|
fn test_iadd_5_6(){
|
||||||
|
a := iadd(5,6)
|
||||||
|
assert a == 11
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
Module {
|
||||||
|
name: 'project_with_tests_for_main',
|
||||||
|
description: 'This project demonstrates the ability to test functions in the main module',
|
||||||
|
dependencies: []
|
||||||
|
}
|
|
@ -63,7 +63,8 @@ fn color(kind, msg string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatted_error - `kind` may be 'error' or 'warn'
|
// formatted_error - `kind` may be 'error' or 'warn'
|
||||||
pub fn formatted_error(kind, emsg, filepath string, pos token.Position) string {
|
pub fn formatted_error(kind, omsg, filepath string, pos token.Position) string {
|
||||||
|
emsg := omsg.replace('main.', '')
|
||||||
mut path := filepath
|
mut path := filepath
|
||||||
verror_paths_override := os.getenv('VERROR_PATHS')
|
verror_paths_override := os.getenv('VERROR_PATHS')
|
||||||
if verror_paths_override == 'absolute' {
|
if verror_paths_override == 'absolute' {
|
||||||
|
|
|
@ -331,3 +331,15 @@ pub fn ensure_modules_for_all_tools_are_installed(is_verbose bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn strip_mod_name(name string) string {
|
||||||
|
return name.all_after_last('.')
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn strip_main_name(name string) string {
|
||||||
|
return name.replace('main.','')
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn no_dots(s string) string {
|
||||||
|
return s.replace('.', '__')
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue