Skip to content

Commit 4e9fa3e

Browse files
authored
more C functions and methods; check-md --backend flag (#336)
1 parent 68dafa0 commit 4e9fa3e

14 files changed

Lines changed: 188 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,24 @@ All notable changes are documented in this file.
88
### Standard Library
99
- builtin:
1010
- _[C]_ string methods: `split()`, `split_lines()`, `trim_space()`, `is_upper()`
11+
- _[C]_ []string method: `join()`
1112
- os:
12-
- _[C]_ functions: `read_lines()`
13+
- _[C]_ functions: `read_lines()`, `getenv()`, `setenv()`, `tmp_dir()`
1314

1415
### C Backend
1516
- Increase test coverage
1617
- arrays
1718
- Implement comparison
1819
- Implement auto-string conversion
1920

21+
### CLI and Tooling
22+
- check-md: add `--backend` option
23+
2024
### Testing
2125
- respect `.c.bt` and `.js.bt` file extensions for test files
2226

2327
### Other Changes
28+
- gen: do not generate main call in script mode
2429
- remove `test-all` tool
2530

2631

cli/tools/check-md.bt

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
// SPDX-FileCopyrightText: Lukas Neubert <lukas.neubert@proton.me>
1+
// SPDX-FileCopyrightText: Lukas Neubert
22
// SPDX-License-Identifier: MIT
33
package main
44

5+
import cli.options
56
import os
67

78
struct CodeBlock {
@@ -11,35 +12,52 @@ struct CodeBlock {
1112
}
1213

1314
fun main() {
14-
if os.ARGS.length <= 2 {
15-
eprintln('check-md error: please provide a file to be checked')
15+
mut opt := options.new_option_parser(os.user_args())
16+
17+
backend := opt.string('backend', `b`, 'js')
18+
if backend != 'js' and backend != 'c' {
19+
eprintln('check-md: invalid backend')
20+
exit(1)
21+
}
22+
args := opt.remaining()
23+
24+
if args.length == 0 {
25+
eprintln('check-md: provide a file to be checked')
1626
exit(1)
1727
}
18-
file := os.ARGS[2]
28+
29+
file := args[0]
1930
if not file.ends_with('.md') {
2031
eprintln('check-md error: file must be a markdown file')
2132
exit(1)
2233
}
34+
2335
println('Checking code blocks in ${file}...')
2436
blocks := collect_code_blocks(file)
25-
mut has_errors := false
37+
38+
mut nr_errors := 0
2639
for block in blocks {
27-
res := check_block_runs(block)
40+
res := check_block_runs(block, backend)
2841
if not res {
29-
has_errors = true
42+
nr_errors += 1
3043
}
3144
}
32-
if has_errors {
45+
46+
println('ok: ${blocks.length - nr_errors}, failed: ${nr_errors}, total: ${blocks.length}')
47+
48+
if nr_errors > 0 {
3349
exit(1)
3450
}
3551
}
3652

3753
fun collect_code_blocks(path string) []CodeBlock{
3854
lines := os.read_lines(path)
55+
3956
mut blocks := []CodeBlock
4057
mut inside_block := false
4158
mut start := 0
4259
mut text := ''
60+
4361
for i, line in lines {
4462
if line.starts_with('```bait') {
4563
inside_block = true
@@ -56,13 +74,17 @@ fun collect_code_blocks(path string) []CodeBlock{
5674
text += line + '\n'
5775
}
5876
}
77+
5978
return blocks
6079
}
6180

62-
fun check_block_runs(block CodeBlock) bool {
63-
tmp_file := os.join_path(os.tmp_dir(), ['tmp.bt'])
81+
fun check_block_runs(block CodeBlock, backend string) bool {
82+
tmp_name := 'check-md-${block.start_idx}.bt'
83+
tmp_file := os.join_path(os.tmp_dir(), [tmp_name])
6484
os.write_file(tmp_file, block.text)
65-
res := os.exec('bun ${$BAITEXE} ${tmp_file} --script')
85+
86+
res := os.exec('bun ${$BAITEXE} "${tmp_file}" --script --backend ${backend}')
87+
6688
if res.code != 0 {
6789
println('Error in block ${block.start_idx + 1}:${block.end_idx + 1}')
6890
println(res.stderr)

lib/bait/gen/c/cgen.bt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ fun (g Gen) headers() string {
9595
fun (mut g Gen) c_main() {
9696
g.writeln('int main(int argc, char* argv[]) {')
9797
g.writeln(g.main_inits_out)
98-
g.writeln('\tbait_main();')
98+
if not g.pref.is_script {
99+
g.writeln('\tbait_main();')
100+
}
99101
g.writeln('\treturn 0;')
100102
g.writeln('}')
101103
}

lib/bait/gen/js/jsgen.bt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub fun gen(files []ast.File, table ast.Table, pref preference.Prefs) string {
8585
g.out += "\n"
8686
}
8787

88-
if not pref.is_library {
88+
if not g.pref.is_library and not g.pref.is_script {
8989
g.main_call()
9090
}
9191

lib/bait/preference/preference.bt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ pub fun parse_args(args []string) Prefs {
145145
p.should_run = true
146146
p.keep_exe = true
147147
p.is_test = true
148+
p.is_script = false // `test` command implies compilation, so script mode is disabled
148149
}
149150

150151
// Set default out name if empty

lib/builtin/array.c.bt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: Lukas Neubert <lukas.neubert@proton.me>
1+
// SPDX-FileCopyrightText: Lukas Neubert
22
// SPDX-License-Identifier: MIT
33
package builtin
44

@@ -107,3 +107,9 @@ pub fun (a Array) slice(start i32, end i32) Array {
107107
elem_size = a.elem_size
108108
}
109109
}
110+
111+
pub fun (a Array) copy() Array {
112+
mut b := new_array(a.length, a.cap, a.elem_size)
113+
#C.memcpy(b.data, a.data, a.length * a.elem_size)
114+
return b
115+
}

lib/builtin/array.js.bt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub fun (a Array) concat(b Array) Array {
8686
}
8787
}
8888

89+
// TODO rename to clone()
8990
pub fun (a Array) copy() Array {
9091
return Array{
9192
data = #JS.'[...a.data]' as #JS.Array

lib/builtin/string.c.bt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,43 @@ fun (a string) eq (b string) bool {
234234
return true
235235
}
236236

237+
pub fun (arr []string) join(sep string) string {
238+
if arr.length == 0 {
239+
return ''
240+
}
241+
242+
if arr.length == 1 {
243+
return arr[0]
244+
}
245+
246+
mut new_len := 0
247+
for s in arr {
248+
new_len += s.length
249+
}
250+
new_len += sep.length * (arr.length - 1)
251+
252+
mut buf := #C.calloc(1, new_len + 1)
253+
mut pos := 0
254+
255+
for i, s in arr {
256+
if i > 0 and sep.length > 0 {
257+
#C.memcpy(#C.'buf + pos' as &void, sep.str, sep.length)
258+
pos += sep.length
259+
}
260+
261+
if s.length > 0 {
262+
#C.memcpy(#C.'buf + pos' as &void, s.str, s.length)
263+
pos += s.length
264+
}
265+
}
266+
267+
buf[new_len] = 0 as u8
268+
return string{
269+
str = buf
270+
length = new_len
271+
}
272+
}
273+
237274
pub fun from_c_string(cs &u8) string {
238275
return string{
239276
str = cs

lib/builtin/tests/array_test.bt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,11 @@ fun test_index_and_index_last() {
1717
assert strings.index('c') == 2
1818
assert strings.index_last('c') == 3
1919
}
20+
21+
fun test_copy() {
22+
mut a := [1, 2, 3]
23+
b := a.copy()
24+
a[0] = 9
25+
assert a == [9, 2, 3]
26+
assert b == [1, 2, 3]
27+
}

lib/builtin/tests/string_test.bt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ fun test_split_lines() {
4040
assert 'foo\r\nbar\r\n'.split_lines() == ['foo', 'bar']
4141
}
4242

43-
44-
4543
fun test_trim_space() {
4644
assert ' hello '.trim_space() == 'hello'
4745
assert '\t\nfoo\r\n'.trim_space() == 'foo'
@@ -66,3 +64,11 @@ fun test_is_upper() {
6664
assert not '123'.is_upper()
6765
assert 'ABC123'.is_upper()
6866
}
67+
68+
fun test_join() {
69+
assert ([]string).join(',') == ''
70+
assert ['a'].join(',') == 'a'
71+
assert ['a', 'b', 'c'].join(',') == 'a,b,c'
72+
assert ['a', '', 'c'].join('-') == 'a--c'
73+
assert ['a', 'b'].join(', ') == 'a, b'
74+
}

0 commit comments

Comments
 (0)