Skip to content

Commit daa01b0

Browse files
authored
Merge pull request #284 from bext-lang/target-api-versioning
Introduce Target API versioning
2 parents a13635b + 294355d commit daa01b0

7 files changed

Lines changed: 102 additions & 56 deletions

File tree

src/b.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,13 +1190,13 @@ pub unsafe fn get_garbage_base(path: *const c_char, target: Target) -> Option<*m
11901190
write_entire_file(gitignore_path, c!("*") as *const c_void, 1)?;
11911191
}
11921192

1193-
Some(temp_sprintf(c!("%s/%s.%s"), garbage_dir, filename, target.api.name))
1193+
Some(temp_sprintf(c!("%s/%s.%s"), garbage_dir, filename, target.api.name()))
11941194
}
11951195

11961196
pub unsafe fn print_available_targets(targets: *const [Target]) {
11971197
fprintf(stderr(), c!("Compilation targets:\n"));
11981198
for i in 0..targets.len() {
1199-
fprintf(stderr(), c!(" %s\n"), (*targets)[i].api.name);
1199+
fprintf(stderr(), c!(" %s\n"), (*targets)[i].api.name());
12001200
}
12011201
}
12021202

@@ -1218,7 +1218,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
12181218
}
12191219

12201220
let default_target_name = if let Some(default_target) = default_target {
1221-
default_target.api.name
1221+
default_target.api.name()
12221222
} else {
12231223
ptr::null()
12241224
};
@@ -1302,7 +1302,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13021302
log(Log_Level::WARNING, c!("Flag -%s is DEPRECATED! Interpreting it as `-%s %s` instead."), flag_name(linker), PARAM_FLAG_NAME, codegen_arg);
13031303
}
13041304

1305-
let gen = (target.api.new)(&mut c.arena, da_slice(*codegen_args))?;
1305+
let gen = target.new(&mut c.arena, da_slice(*codegen_args))?;
13061306

13071307
if input_paths.count == 0 {
13081308
usage();
@@ -1379,12 +1379,12 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13791379
}
13801380

13811381
let program_path = if (*output_path).is_null() {
1382-
temp_sprintf(c!("%s%s"), temp_strip_file_ext(*input_paths.items), target.api.file_ext)
1382+
temp_sprintf(c!("%s%s"), temp_strip_file_ext(*input_paths.items), target.file_ext())
13831383
} else {
13841384
if get_file_ext(*output_path).is_some() {
13851385
*output_path
13861386
} else {
1387-
temp_sprintf(c!("%s%s"), *output_path, target.api.file_ext)
1387+
temp_sprintf(c!("%s%s"), *output_path, target.file_ext())
13881388
}
13891389
};
13901390

@@ -1403,11 +1403,11 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14031403
let garbage_base = get_garbage_base(program_path, target)?;
14041404

14051405
if !*nobuild {
1406-
(target.api.build)(gen, &c.program, program_path, garbage_base, *nostdlib, *debug)?;
1406+
target.build(gen, &c.program, program_path, garbage_base, *nostdlib, *debug)?;
14071407
}
14081408

14091409
if *run {
1410-
(target.api.run)(gen, program_path, da_slice(run_args))?
1410+
target.run(gen, program_path, da_slice(run_args))?
14111411
}
14121412

14131413
Some(())

src/btest.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ pub unsafe fn execute_test(
134134
) -> Option<Outcome> {
135135
// TODO: add timeouts for running and building in case they go into infinite loop or something
136136
let input_path = temp_sprintf(c!("%s/%s.b"), test_folder, name);
137-
let program_path = temp_sprintf(c!("%s/%s.%s%s"), GARBAGE_FOLDER, name, target.api.name, target.api.file_ext);
138-
let stdout_path = temp_sprintf(c!("%s/%s.%s.stdout.txt"), GARBAGE_FOLDER, name, target.api.name);
137+
let program_path = temp_sprintf(c!("%s/%s.%s%s"), GARBAGE_FOLDER, name, target.api.name(), target.file_ext());
138+
let stdout_path = temp_sprintf(c!("%s/%s.%s.stdout.txt"), GARBAGE_FOLDER, name, target.api.name());
139139
cmd_append! {
140140
cmd,
141141
if cfg!(target_os = "windows") {
@@ -144,7 +144,7 @@ pub unsafe fn execute_test(
144144
c!("./build/b")
145145
},
146146
input_path,
147-
c!("-t"), target.api.name,
147+
c!("-t"), target.api.name(),
148148
c!("-o"), program_path,
149149
}
150150
if quiet {
@@ -162,14 +162,14 @@ pub unsafe fn execute_test(
162162
c!("./build/b")
163163
},
164164
input_path,
165-
c!("-t"), target.api.name,
165+
c!("-t"), target.api.name(),
166166
c!("-o"), program_path,
167167
c!("-q"),
168168
c!("-nobuild"),
169169
c!("-run"),
170170
}
171171
// Hack for Uxn
172-
if strcmp(target.api.name, c!("uxn")) == 0 {
172+
if strcmp(target.api.name(), c!("uxn")) == 0 {
173173
cmd_append!(cmd, c!("-C"), c!("runner=uxncli"));
174174
}
175175
let mut fdout = fd_open_for_write(stdout_path);
@@ -235,7 +235,7 @@ pub unsafe fn print_top_labels(targets: *const [Target], stats_by_target: *const
235235
printf(c!("│ "));
236236
}
237237
// TODO: these fancy unicode characters don't work well on mingw32 build via wine
238-
printf(c!("┌─%-*s"), col_width - 2*j, target.api.name);
238+
printf(c!("┌─%-*s"), col_width - 2*j, target.api.name());
239239
print_report_stats(stats)
240240
}
241241
}
@@ -249,7 +249,7 @@ pub unsafe fn print_bottom_labels(targets: *const [Target], stats_by_target: *co
249249
for _ in 0..j {
250250
printf(c!("│ "));
251251
}
252-
printf(c!("└─%-*s"), col_width - 2*j, target.api.name);
252+
printf(c!("└─%-*s"), col_width - 2*j, target.api.name());
253253
print_report_stats(stats)
254254
}
255255
}
@@ -383,7 +383,7 @@ pub unsafe fn generate_report(reports: *const [Report], stats_by_target: *const
383383
let mut col_width = 0;
384384
for j in 0..targets.len() {
385385
let target = (*targets)[j];
386-
let width = 2*(j + 1) + strlen(target.api.name);
386+
let width = 2*(j + 1) + strlen(target.api.name());
387387
col_width = cmp::max(col_width, width);
388388
}
389389

@@ -423,7 +423,7 @@ type TestTable = Array<TestRow>;
423423
pub unsafe fn test_table_find_row(tt: *mut TestTable, case_name: *const c_char, target: Target) -> Option<*mut TestRow> {
424424
for i in 0..(*tt).count {
425425
let row = (*tt).items.add(i);
426-
if strcmp((*row).target.api.name, target.api.name) == 0 && strcmp((*row).case_name, case_name) == 0 {
426+
if strcmp((*row).target.api.name(), target.api.name()) == 0 && strcmp((*row).case_name, case_name) == 0 {
427427
return Some(row)
428428
}
429429
}
@@ -516,15 +516,15 @@ pub unsafe fn load_tt_from_json_file_if_exists(
516516
// TODO: report the location of existing_row here as a NOTE
517517
// This requires keeping track of location in TestRow structure. Which requires location tracking capabilities
518518
// comparable to lexer.rs but in jim/jimp.
519-
jimp_diagf(jimp, c!("WARNING: Redefinition of the row case `%s`, target `%s`. We are using only the first definition. All the rest are gonna be prunned"), case_name, target.api.name);
519+
jimp_diagf(jimp, c!("WARNING: Redefinition of the row case `%s`, target `%s`. We are using only the first definition. All the rest are gonna be prunned"), case_name, target.api.name());
520520
// TODO: memory leak, we are dropping the whole row here
521521
continue 'table;
522522
}
523523

524524
let case_path = temp_sprintf(c!("%s/%s.b"), test_folder, case_name);
525525
if !file_exists(case_path)? {
526526
(*jimp).token_start = saved_point;
527-
jimp_diagf(jimp, c!("WARNING: %s does not exist. Ignoring case `%s`, target `%s` ...\n"), case_path, case_name, target.api.name);
527+
jimp_diagf(jimp, c!("WARNING: %s does not exist. Ignoring case `%s`, target `%s` ...\n"), case_path, case_name, target.api.name());
528528
// TODO: memory leak, we are dropping the whole row here
529529
continue 'table;
530530
}
@@ -559,7 +559,7 @@ pub unsafe fn save_tt_to_json_file(
559559
jim_member_key(jim, c!("case"));
560560
jim_string(jim, (*row).case_name);
561561
jim_member_key(jim, c!("target"));
562-
jim_string(jim, (*row).target.api.name);
562+
jim_string(jim, (*row).target.api.name());
563563
jim_member_key(jim, c!("expected_stdout"));
564564
jim_string(jim, (*row).expected_stdout);
565565
jim_member_key(jim, c!("state"));
@@ -776,7 +776,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> {
776776
let pattern = *(*target_flags).items.add(j);
777777
for j in 0..all_targets.count {
778778
let target = *all_targets.items.add(j);
779-
let name = target.api.name;
779+
let name = target.api.name();
780780
if matches_glob(pattern, name)? {
781781
da_append(&mut selected_targets, target);
782782
added_anything = true;
@@ -794,7 +794,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> {
794794
let mut matches_any = false;
795795
'exclude: for j in 0..(*exclude_target_flags).count {
796796
let pattern = *(*exclude_target_flags).items.add(j);
797-
if matches_glob(pattern, target.api.name)? {
797+
if matches_glob(pattern, target.api.name())? {
798798
matches_any = true;
799799
break 'exclude;
800800
}
@@ -858,7 +858,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> {
858858
fprintf(stderr(), c!("Compilation targets:\n"));
859859
for i in 0..targets.count {
860860
let target = *targets.items.add(i);
861-
fprintf(stderr(), c!(" %s\n"), target.api.name);
861+
fprintf(stderr(), c!(" %s\n"), target.api.name());
862862
}
863863
return Some(());
864864
}
@@ -913,15 +913,15 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> {
913913
let mut target_width = 0;
914914
for j in 0..targets.count {
915915
let target = *targets.items.add(j);
916-
target_width = cmp::max(target_width, strlen(target.api.name));
916+
target_width = cmp::max(target_width, strlen(target.api.name()));
917917
}
918918

919919
let mut tt = load_tt_from_json_file_if_exists(da_slice(all_targets), json_path, *test_folder, &mut sb, &mut jimp)?;
920920
for i in 0..cases.count {
921921
let case_name = *cases.items.add(i);
922922
for j in 0..targets.count {
923923
let target = *targets.items.add(j);
924-
log(Log_Level::INFO, c!("disabling %-*s for %-*s"), case_width, case_name, target_width, target.api.name);
924+
log(Log_Level::INFO, c!("disabling %-*s for %-*s"), case_width, case_name, target_width, target.api.name());
925925
if let Some(row) = test_table_find_row(&mut tt, case_name, target) {
926926
(*row).state = TestState::Disabled;
927927
if !(*comment).is_null() {

src/codegen/gas_aarch64/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ struct Gas_AArch64 {
505505
}
506506

507507
pub unsafe fn get_apis(targets: *mut Array<TargetAPI>) {
508-
da_append(targets, TargetAPI {
508+
da_append(targets, TargetAPI::V1 {
509509
name: c!("gas-aarch64-linux"),
510510
file_ext: c!(""),
511511
new,
@@ -517,7 +517,7 @@ pub unsafe fn get_apis(targets: *mut Array<TargetAPI>) {
517517
},
518518
});
519519

520-
da_append(targets, TargetAPI {
520+
da_append(targets, TargetAPI::V1 {
521521
name: c!("gas-aarch64-darwin"),
522522
file_ext: c!(""),
523523
new,

src/codegen/gas_x86_64/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ struct Gas_x86_64 {
637637
}
638638

639639
pub unsafe fn get_apis(targets: *mut Array<TargetAPI>) {
640-
da_append(targets, TargetAPI {
640+
da_append(targets, TargetAPI::V1 {
641641
name: c!("gas-x86_64-linux"),
642642
file_ext: c!(""),
643643
new,
@@ -649,7 +649,7 @@ pub unsafe fn get_apis(targets: *mut Array<TargetAPI>) {
649649
},
650650
});
651651

652-
da_append(targets, TargetAPI {
652+
da_append(targets, TargetAPI::V1 {
653653
name: c!("gas-x86_64-windows"),
654654
file_ext: c!(".exe"),
655655
new,
@@ -661,7 +661,7 @@ pub unsafe fn get_apis(targets: *mut Array<TargetAPI>) {
661661
},
662662
});
663663

664-
da_append(targets, TargetAPI {
664+
da_append(targets, TargetAPI::V1 {
665665
name: c!("gas-x86_64-darwin"),
666666
file_ext: c!(""),
667667
new,

src/codegen/mos6502.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1557,7 +1557,7 @@ struct Mos6502 {
15571557
}
15581558

15591559
pub unsafe fn get_apis(targets: *mut Array<TargetAPI>) {
1560-
da_append(targets, TargetAPI {
1560+
da_append(targets, TargetAPI::V1 {
15611561
name: c!("6502-posix"),
15621562
file_ext: c!(".6502"),
15631563
new,

src/codegen/uxn/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ struct Uxn {
165165
}
166166

167167
pub unsafe fn get_apis(targets: *mut Array<TargetAPI>) {
168-
da_append(targets, TargetAPI {
168+
da_append(targets, TargetAPI::V1 {
169169
name: c!("uxn"),
170170
file_ext: c!(".rom"),
171171
new,

src/targets.rs

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,60 @@ impl Target {
1717
pub unsafe fn by_name(targets: *const [Target], name: *const c_char) -> Option<Target> {
1818
for i in 0..targets.len() {
1919
let target = (*targets)[i];
20-
if strcmp(target.api.name, name) == 0 {
20+
if strcmp(target.name(), name) == 0 {
2121
return Some(target);
2222
}
2323
}
2424
None
2525
}
26+
pub unsafe fn name(self) -> *const c_char {
27+
self.api.name()
28+
}
29+
pub unsafe fn new(self, a: *mut arena::Arena, args: *const [*const c_char]) -> Option<*mut c_void> {
30+
match self.api {
31+
TargetAPI::V1 { new, .. } => new(a, args)
32+
}
33+
}
34+
pub unsafe fn build (
35+
self,
36+
gen: *mut c_void,
37+
program: *const Program,
38+
program_path: *const c_char,
39+
garbage_base: *const c_char,
40+
nostdlib: bool,
41+
debug: bool,
42+
) -> Option<()> {
43+
match self.api {
44+
TargetAPI::V1 { build, .. } => build(gen, program, program_path, garbage_base, nostdlib, debug),
45+
}
46+
}
47+
pub unsafe fn run (
48+
self,
49+
gen: *mut c_void,
50+
program_path: *const c_char,
51+
run_args: *const [*const c_char],
52+
) -> Option<()> {
53+
match self.api {
54+
TargetAPI::V1 { run, .. } => run(gen, program_path, run_args),
55+
}
56+
}
57+
pub unsafe fn file_ext(self) -> *const c_char {
58+
match self.api {
59+
TargetAPI::V1 { file_ext, .. } => file_ext,
60+
}
61+
}
2662
}
2763

2864
pub unsafe fn register_apis(targets: *mut Array<Target>, apis: *const [TargetAPI], codegen_name: *const c_char) -> Option<()> {
2965
for i in 0..apis.len() {
3066
let api = (*apis)[i];
3167
for j in 0..(*targets).count {
3268
let target = *(*targets).items.add(j);
33-
if strcmp(target.api.name, api.name) == 0 {
69+
if strcmp(target.name(), api.name()) == 0 {
3470
if strcmp(target.codegen_name, codegen_name) == 0 {
35-
log(Log_Level::ERROR, c!("TARGET NAME CONFLICT: Codegen %s defines target %s more than once"), codegen_name, api.name);
71+
log(Log_Level::ERROR, c!("TARGET NAME CONFLICT: Codegen %s defines target %s more than once"), codegen_name, api.name());
3672
} else {
37-
log(Log_Level::ERROR, c!("TARGET NAME CONFLICT: Codegens %s and %s define the same target %s"), codegen_name, target.codegen_name, api.name);
73+
log(Log_Level::ERROR, c!("TARGET NAME CONFLICT: Codegens %s and %s define the same target %s"), codegen_name, target.codegen_name, api.name());
3874
}
3975
return None;
4076
}
@@ -45,26 +81,36 @@ pub unsafe fn register_apis(targets: *mut Array<Target>, apis: *const [TargetAPI
4581
}
4682

4783
#[derive(Clone, Copy)]
48-
pub struct TargetAPI {
49-
pub name: *const c_char,
50-
pub file_ext: *const c_char,
51-
pub new: unsafe fn(
52-
a: *mut arena::Arena,
53-
args: *const [*const c_char]
54-
) -> Option<*mut c_void>,
55-
pub build: unsafe fn(
56-
gen: *mut c_void,
57-
program: *const Program,
58-
program_path: *const c_char,
59-
garbage_base: *const c_char,
60-
nostdlib: bool,
61-
debug: bool,
62-
) -> Option<()>,
63-
pub run: unsafe fn(
64-
gen: *mut c_void,
65-
program_path: *const c_char,
66-
run_args: *const [*const c_char],
67-
) -> Option<()>,
84+
pub enum TargetAPI {
85+
V1 {
86+
name: *const c_char,
87+
file_ext: *const c_char,
88+
new: unsafe fn(
89+
a: *mut arena::Arena,
90+
args: *const [*const c_char]
91+
) -> Option<*mut c_void>,
92+
build: unsafe fn(
93+
gen: *mut c_void,
94+
program: *const Program,
95+
program_path: *const c_char,
96+
garbage_base: *const c_char,
97+
nostdlib: bool,
98+
debug: bool,
99+
) -> Option<()>,
100+
run: unsafe fn(
101+
gen: *mut c_void,
102+
program_path: *const c_char,
103+
run_args: *const [*const c_char],
104+
) -> Option<()>,
105+
}
106+
}
107+
108+
impl TargetAPI {
109+
pub unsafe fn name(self) -> *const c_char {
110+
match self {
111+
TargetAPI::V1 { name, .. } => name,
112+
}
113+
}
68114
}
69115

70116
#[derive(Clone, Copy, PartialEq, Eq)]

0 commit comments

Comments
 (0)