mirror of
https://github.com/ganelson/inform.git
synced 2024-06-01 07:48:35 +03:00
Added arch module and inbuild unit testing
This commit is contained in:
parent
7043d6c855
commit
b8c2a178e8
2
inbuild/.gitignore
vendored
2
inbuild/.gitignore
vendored
|
@ -12,3 +12,5 @@ Tests/_Results_Actual/
|
|||
|
||||
inbuild.mk
|
||||
|
||||
Tests/Units/_Results_Actual/
|
||||
|
||||
|
|
|
@ -23,11 +23,13 @@ int dry_run_mode = FALSE;
|
|||
linked_list *targets = NULL; /* of |inbuild_copy| */
|
||||
inbuild_nest *destination_nest = NULL;
|
||||
text_stream *filter_text = NULL;
|
||||
text_stream *unit_test = NULL;
|
||||
linked_list *inbuild_nest_list = NULL;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Foundation::start();
|
||||
WordsModule::start();
|
||||
ArchModule::start();
|
||||
InbuildModule::start();
|
||||
targets = NEW_LINKED_LIST(inbuild_copy);
|
||||
@<Read the command line@>;
|
||||
|
@ -37,33 +39,40 @@ int main(int argc, char **argv) {
|
|||
if (path_to_tools) BM = BuildSteps::methodology(path_to_tools, FALSE);
|
||||
else BM = BuildSteps::methodology(Pathnames::up(path_to_inbuild), TRUE);
|
||||
if (dry_run_mode == FALSE) BM->methodology = SHELL_METHODOLOGY;
|
||||
if (Str::len(filter_text) > 0) {
|
||||
TEMPORARY_TEXT(errors);
|
||||
inbuild_requirement *req = Requirements::from_text(filter_text, errors);
|
||||
if (Str::len(errors) > 0) {
|
||||
Errors::with_text("requirement malformed: %S", errors);
|
||||
} else {
|
||||
linked_list *L = NEW_LINKED_LIST(inbuild_search_result);
|
||||
Nests::search_for(req, inbuild_nest_list, L);
|
||||
inbuild_search_result *R;
|
||||
LOOP_OVER_LINKED_LIST(R, inbuild_search_result, L) {
|
||||
ADD_TO_LINKED_LIST(R->copy, inbuild_copy, targets);
|
||||
if (Str::len(unit_test) > 0) {
|
||||
BM->methodology = DRY_RUN_METHODOLOGY;
|
||||
if (Str::eq(unit_test, I"compatibility")) Compatibility::test(STDOUT);
|
||||
else Errors::with_text("no such unit test: %S", unit_test);
|
||||
} else {
|
||||
if (Str::len(filter_text) > 0) {
|
||||
TEMPORARY_TEXT(errors);
|
||||
inbuild_requirement *req = Requirements::from_text(filter_text, errors);
|
||||
if (Str::len(errors) > 0) {
|
||||
Errors::with_text("requirement malformed: %S", errors);
|
||||
} else {
|
||||
linked_list *L = NEW_LINKED_LIST(inbuild_search_result);
|
||||
Nests::search_for(req, inbuild_nest_list, L);
|
||||
inbuild_search_result *R;
|
||||
LOOP_OVER_LINKED_LIST(R, inbuild_search_result, L) {
|
||||
ADD_TO_LINKED_LIST(R->copy, inbuild_copy, targets);
|
||||
}
|
||||
}
|
||||
DISCARD_TEXT(errors);
|
||||
}
|
||||
DISCARD_TEXT(errors);
|
||||
}
|
||||
inbuild_copy *C;
|
||||
LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets) {
|
||||
switch (inbuild_task) {
|
||||
case INSPECT_TTASK: Copies::inspect(STDOUT, C); break;
|
||||
case GRAPH_TTASK: Graphs::describe(STDOUT, C->vertex, TRUE); break;
|
||||
case BUILD_TTASK: Graphs::build(C->vertex, BM); break;
|
||||
case REBUILD_TTASK: Graphs::rebuild(C->vertex, BM); break;
|
||||
case COPY_TO_TTASK: if (destination_nest) Nests::copy_to(C, destination_nest, FALSE, BM); break;
|
||||
case SYNC_TO_TTASK: if (destination_nest) Nests::copy_to(C, destination_nest, TRUE, BM); break;
|
||||
inbuild_copy *C;
|
||||
LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets) {
|
||||
switch (inbuild_task) {
|
||||
case INSPECT_TTASK: Copies::inspect(STDOUT, C); break;
|
||||
case GRAPH_TTASK: Graphs::describe(STDOUT, C->vertex, TRUE); break;
|
||||
case BUILD_TTASK: Graphs::build(C->vertex, BM); break;
|
||||
case REBUILD_TTASK: Graphs::rebuild(C->vertex, BM); break;
|
||||
case COPY_TO_TTASK: if (destination_nest) Nests::copy_to(C, destination_nest, FALSE, BM); break;
|
||||
case SYNC_TO_TTASK: if (destination_nest) Nests::copy_to(C, destination_nest, TRUE, BM); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
WordsModule::end();
|
||||
ArchModule::end();
|
||||
InbuildModule::end();
|
||||
Foundation::end();
|
||||
return 0;
|
||||
|
@ -81,6 +90,7 @@ int main(int argc, char **argv) {
|
|||
@e MATCHING_CLSW
|
||||
@e COPY_TO_CLSW
|
||||
@e SYNC_TO_CLSW
|
||||
@e UNIT_TEST_CLSW
|
||||
|
||||
@<Read the command line@> =
|
||||
CommandLine::declare_heading(
|
||||
|
@ -106,6 +116,8 @@ int main(int argc, char **argv) {
|
|||
L"apply to all works in nest(s) matching requirement X");
|
||||
CommandLine::declare_switch(CONTENTS_OF_CLSW, L"contents-of", 2,
|
||||
L"apply to all targets in the directory X");
|
||||
CommandLine::declare_switch(UNIT_TEST_CLSW, L"unit-test", 2,
|
||||
L"perform unit test X (for debugging inbuild only)");
|
||||
Inbuild::declare_options();
|
||||
|
||||
CommandLine::read(argc, argv, NULL, &Main::option, &Main::bareword);
|
||||
|
@ -152,6 +164,7 @@ void Main::option(int id, int val, text_stream *arg, void *state) {
|
|||
case SYNC_TO_CLSW: inbuild_task = SYNC_TO_TTASK;
|
||||
destination_nest = Nests::new(Pathnames::from_text(arg));
|
||||
break;
|
||||
case UNIT_TEST_CLSW: unit_test = Str::duplicate(arg); break;
|
||||
}
|
||||
Inbuild::option(id, val, arg, state);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ Version Name: Avignon
|
|||
|
||||
Import: foundation
|
||||
Import: inform7/words
|
||||
Import: arch
|
||||
Import: inbuild
|
||||
|
||||
Preliminaries
|
||||
|
|
14
inbuild/Tests/Units/_Results_Ideal/compatibility.txt
Normal file
14
inbuild/Tests/Units/_Results_Ideal/compatibility.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
'for all': for all: 16=yes 16d=yes 32=yes 32d=yes
|
||||
'all': for all: 16=yes 16d=yes 32=yes 32d=yes
|
||||
'not for all': not a valid compatibility specification
|
||||
'not all': not a valid compatibility specification
|
||||
'for none': for none: 16=no 16d=no 32=no 32d=no
|
||||
'none': for none: 16=no 16d=no 32=no 32d=no
|
||||
'not for none': not a valid compatibility specification
|
||||
'not none': not a valid compatibility specification
|
||||
'for 16d': for 16d: 16=no 16d=yes 32=no 32d=no
|
||||
'not for 32': not for 32: 16=yes 16d=yes 32=no 32d=yes
|
||||
'for 16d or 32d': for 16d or 32d: 16=no 16d=yes 32=no 32d=yes
|
||||
'not for 32 or 16': not for 32 or 16: 16=no 16d=yes 32=no 32d=yes
|
||||
'for 16d, 32d or 32': for 16d, 32d or 32: 16=no 16d=yes 32=yes 32d=yes
|
||||
'not for 16d, 32d or 32': not for 16d, 32d or 32: 16=yes 16d=no 32=no 32d=no
|
143
inbuild/Tests/Units/compatibility.txt
Normal file
143
inbuild/Tests/Units/compatibility.txt
Normal file
|
@ -0,0 +1,143 @@
|
|||
schema
|
||||
alpha.beta()
|
||||
end
|
||||
schema
|
||||
alpha.beta(x)
|
||||
end
|
||||
schema
|
||||
routine.call(x)
|
||||
end
|
||||
schema
|
||||
(alpha.beta)(x)
|
||||
end
|
||||
schema
|
||||
debug_rules = 2; say__p = 1;
|
||||
"Rules tracing now switched to ~all~. Type ~rules off~ to switch it off again.";
|
||||
end
|
||||
schema
|
||||
@erase_window -1;
|
||||
end
|
||||
schema
|
||||
restore Somewhere;
|
||||
.Somewhere; print "Here!";
|
||||
end
|
||||
schema
|
||||
"Hello, this
|
||||
is a multiline string literal";
|
||||
end
|
||||
schema
|
||||
for (n=0:((n<RE_Subexpressions-->10) && (n<10)): n++)
|
||||
print n;
|
||||
end
|
||||
schema
|
||||
spaces j;
|
||||
print (I7_string) str;
|
||||
end
|
||||
schema
|
||||
if (i == 1) print "Okay";
|
||||
else "*** Arrcpy doesn't support this ***";
|
||||
end
|
||||
schema
|
||||
a-1
|
||||
end
|
||||
schema
|
||||
do {
|
||||
print "Hi!";
|
||||
} until (x);
|
||||
end
|
||||
schema
|
||||
do {
|
||||
if (a) return wd;
|
||||
} until (a);
|
||||
end
|
||||
schema
|
||||
do {
|
||||
if (line_tdata-->index == wd) return wd;
|
||||
index++;
|
||||
} until ((line_token-->index == ENDIT_TOKEN) || (((line_token-->index)->0 & $10) == 0));
|
||||
end
|
||||
schema
|
||||
print "<string ~", (string) o, "~>";
|
||||
end
|
||||
schema
|
||||
switch (Y) {
|
||||
X: print "A ", (string) o;
|
||||
}
|
||||
end
|
||||
schema
|
||||
#ifdef RANKING_TABLE;
|
||||
ANNOUNCE_SCORE_RM('B');
|
||||
j = TableRows(RANKING_TABLE);
|
||||
for (i=j:i>=1:i--)
|
||||
if (score >= TableLookUpEntry(RANKING_TABLE, 1, i)) {
|
||||
v = TableLookUpEntry(RANKING_TABLE, 2, i);
|
||||
TEXT_TY_Say(v);
|
||||
".";
|
||||
}
|
||||
#endif;
|
||||
".";'
|
||||
end
|
||||
schema
|
||||
if (B) if (A) { print "Yes"; }
|
||||
print "No";
|
||||
end
|
||||
schema
|
||||
switch (scope_stage) {
|
||||
2: objectloop (obj)
|
||||
PlaceInScope(obj, true);
|
||||
}
|
||||
end
|
||||
schema
|
||||
while (token ~= NULL) {
|
||||
switch (token-->RE_CCLASS) {
|
||||
DISJUNCTION_RE_CC: token-->RE_CONSTRAINT = -1;
|
||||
QUANTIFIER_RE_CC: token-->RE_CONSTRAINT = -1;
|
||||
}
|
||||
if (token-->RE_DOWN) TEXT_TY_RE_EraseConstraints(token-->RE_DOWN);
|
||||
token = token-->RE_NEXT;
|
||||
}
|
||||
end
|
||||
schema
|
||||
if (b) print 1; else print 2;
|
||||
end
|
||||
schema
|
||||
a: if (b) print 1; else print 2;
|
||||
end
|
||||
schema
|
||||
print_ret "This is ", (char) X, ".";
|
||||
end
|
||||
schema
|
||||
@jl y 0 ?X;
|
||||
@jl y 0 ?~X;
|
||||
@jl y 0 ?rtrue;
|
||||
@jl y 0 ?rfalse;
|
||||
@jl y 0 ?~rtrue;
|
||||
@jl y 0 ?~rfalse;
|
||||
end
|
||||
schema
|
||||
switch (token-->RE_CCLASS) {
|
||||
|
||||
! Should never happen
|
||||
|
||||
CHOICE_RE_CC: return "internal error";
|
||||
|
||||
! Mode switches
|
||||
|
||||
SENSITIVITY_RE_CC:
|
||||
if (token-->RE_PAR1) mode_flags = mode_flags | CIS_MFLAG;
|
||||
else mode_flags = mode_flags & (~CIS_MFLAG);
|
||||
outcome = true;
|
||||
|
||||
! Zero-length positional markers
|
||||
|
||||
ALWAYS_RE_CC:
|
||||
outcome = true;
|
||||
NEVER_RE_CC:
|
||||
START_RE_CC:
|
||||
if (ipos == 0) outcome = true;
|
||||
END_RE_CC:
|
||||
if (BlkValueRead(txt, ipos) == 0) outcome = true;
|
||||
SOMETIMES_RE_CC:
|
||||
outcome = true;
|
||||
}
|
||||
end
|
18
inbuild/Tests/inbuild.intest
Normal file
18
inbuild/Tests/inbuild.intest
Normal file
|
@ -0,0 +1,18 @@
|
|||
-cases [Units] 'inbuild/Tests/Units'
|
||||
|
||||
-recipe [Units]
|
||||
set: $A = $PATH/_Results_Actual/$CASE.txt
|
||||
set: $I = $PATH/_Results_Ideal/$CASE.txt
|
||||
|
||||
mkdir: $PATH/_Results_Actual
|
||||
mkdir: $PATH/_Results_Ideal
|
||||
|
||||
debugger: llvm -f inbuild/Tangled/inbuild -- -unit-test $CASE
|
||||
step: inbuild/Tangled/inbuild -unit-test $CASE >$A 2>&1
|
||||
or: 'failed to produce output' $A
|
||||
|
||||
show: $A
|
||||
|
||||
match text: $A $I
|
||||
or: 'produced incorrect output'
|
||||
-end
|
53
inbuild/arch-module/Chapter 1/Arch Module.w
Normal file
53
inbuild/arch-module/Chapter 1/Arch Module.w
Normal file
|
@ -0,0 +1,53 @@
|
|||
[ArchModule::] Arch Module.
|
||||
|
||||
Setting up the use of this module.
|
||||
|
||||
@h Introduction.
|
||||
|
||||
@d ARCH_MODULE TRUE
|
||||
|
||||
@ To begin with, this module needs to allocate memory:
|
||||
|
||||
@e inter_architecture_MT
|
||||
@e compatibility_specification_MT
|
||||
|
||||
=
|
||||
ALLOCATE_INDIVIDUALLY(inter_architecture)
|
||||
ALLOCATE_INDIVIDUALLY(compatibility_specification)
|
||||
|
||||
@h The beginning.
|
||||
|
||||
=
|
||||
void ArchModule::start(void) {
|
||||
@<Register this module's memory allocation reasons@>;
|
||||
@<Register this module's stream writers@>;
|
||||
@<Register this module's debugging log aspects@>;
|
||||
@<Register this module's debugging log writers@>;
|
||||
@<Register this module's command line switches@>;
|
||||
Architectures::create();
|
||||
}
|
||||
|
||||
@
|
||||
|
||||
@<Register this module's memory allocation reasons@> =
|
||||
;
|
||||
|
||||
@<Register this module's stream writers@> =
|
||||
;
|
||||
|
||||
@
|
||||
|
||||
@<Register this module's debugging log aspects@> =
|
||||
;
|
||||
|
||||
@<Register this module's debugging log writers@> =
|
||||
;
|
||||
|
||||
@<Register this module's command line switches@> =
|
||||
;
|
||||
|
||||
@h The end.
|
||||
|
||||
=
|
||||
void ArchModule::end(void) {
|
||||
}
|
68
inbuild/arch-module/Chapter 2/Architectures.w
Normal file
68
inbuild/arch-module/Chapter 2/Architectures.w
Normal file
|
@ -0,0 +1,68 @@
|
|||
[Architectures::] Architectures.
|
||||
|
||||
To deal with multiple inter architectures.
|
||||
|
||||
@h Architectures.
|
||||
|
||||
=
|
||||
typedef struct inter_architecture {
|
||||
struct text_stream *shorthand; /* such as |32d| */
|
||||
int sixteen_bit;
|
||||
int debug_enabled;
|
||||
MEMORY_MANAGEMENT
|
||||
} inter_architecture;
|
||||
|
||||
inter_architecture *Architectures::new(text_stream *code, int s, int d) {
|
||||
inter_architecture *A = CREATE(inter_architecture);
|
||||
A->shorthand = Str::duplicate(code);
|
||||
A->sixteen_bit = s;
|
||||
A->debug_enabled = d;
|
||||
return A;
|
||||
}
|
||||
|
||||
void Architectures::create(void) {
|
||||
Architectures::new(I"16", TRUE, FALSE);
|
||||
Architectures::new(I"16d", TRUE, TRUE);
|
||||
Architectures::new(I"32", FALSE, FALSE);
|
||||
Architectures::new(I"32d", FALSE, TRUE);
|
||||
}
|
||||
|
||||
filename *Architectures::canonical_binary(pathname *P, inter_architecture *A) {
|
||||
if (A == NULL) internal_error("no arch");
|
||||
TEMPORARY_TEXT(leafname);
|
||||
WRITE_TO(leafname, "arch-%S.interb", A->shorthand);
|
||||
filename *F = Filenames::in_folder(P, leafname);
|
||||
DISCARD_TEXT(leafname);
|
||||
return F;
|
||||
}
|
||||
|
||||
filename *Architectures::canonical_textual(pathname *P, inter_architecture *A) {
|
||||
if (A == NULL) internal_error("no arch");
|
||||
TEMPORARY_TEXT(leafname);
|
||||
WRITE_TO(leafname, "arch-%S.intert", A->shorthand);
|
||||
filename *F = Filenames::in_folder(P, leafname);
|
||||
DISCARD_TEXT(leafname);
|
||||
return F;
|
||||
}
|
||||
|
||||
text_stream *Architectures::to_codename(inter_architecture *A) {
|
||||
if (A == NULL) return NULL;
|
||||
return A->shorthand;
|
||||
}
|
||||
|
||||
inter_architecture *Architectures::from_codename(text_stream *name) {
|
||||
inter_architecture *A;
|
||||
LOOP_OVER(A, inter_architecture)
|
||||
if (Str::eq_insensitive(A->shorthand, name))
|
||||
return A;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Architectures::sixteen_bit(inter_architecture *A) {
|
||||
if (A == NULL) internal_error("no arch");
|
||||
return A->sixteen_bit;
|
||||
}
|
||||
int Architectures::debug_enabled(inter_architecture *A) {
|
||||
if (A == NULL) internal_error("no arch");
|
||||
return A->debug_enabled;
|
||||
}
|
148
inbuild/arch-module/Chapter 2/Compatibility.w
Normal file
148
inbuild/arch-module/Chapter 2/Compatibility.w
Normal file
|
@ -0,0 +1,148 @@
|
|||
[Compatibility::] Compatibility.
|
||||
|
||||
To manage compatibility lists: what can be compiled to what format.
|
||||
|
||||
@
|
||||
|
||||
=
|
||||
typedef struct compatibility_specification {
|
||||
int default_allows;
|
||||
struct linked_list *exceptions; /* of |inter_architecture| */
|
||||
MEMORY_MANAGEMENT
|
||||
} compatibility_specification;
|
||||
|
||||
compatibility_specification *Compatibility::all(void) {
|
||||
compatibility_specification *C = CREATE(compatibility_specification);
|
||||
C->default_allows = TRUE;
|
||||
C->exceptions = NEW_LINKED_LIST(inter_architecture);
|
||||
return C;
|
||||
}
|
||||
|
||||
void Compatibility::write(OUTPUT_STREAM, compatibility_specification *C) {
|
||||
if (C == NULL) { WRITE("for none"); return; }
|
||||
int x = LinkedLists::len(C->exceptions);
|
||||
if (x == 0) {
|
||||
if (C->default_allows) WRITE("for all");
|
||||
else WRITE("for none");
|
||||
} else {
|
||||
if (C->default_allows) WRITE("not ");
|
||||
WRITE("for ");
|
||||
int n = 0;
|
||||
inter_architecture *A;
|
||||
LOOP_OVER_LINKED_LIST(A, inter_architecture, C->exceptions) {
|
||||
n++;
|
||||
if ((n > 1) && (n < x)) WRITE(", ");
|
||||
if ((n > 1) && (n == x)) WRITE(" or ");
|
||||
WRITE("%S", Architectures::to_codename(A));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compatibility_specification *Compatibility::from_text(text_stream *text) {
|
||||
compatibility_specification *C = Compatibility::all();
|
||||
int incorrect = FALSE;
|
||||
if (Str::len(text) == 0) return C;
|
||||
TEMPORARY_TEXT(parse);
|
||||
WRITE_TO(parse, "%S", text);
|
||||
Str::trim_white_space(parse);
|
||||
|
||||
C->default_allows = FALSE;
|
||||
match_results mr = Regexp::create_mr();
|
||||
int negated = FALSE;
|
||||
if (Regexp::match(&mr, parse, L"not (%c+)")) {
|
||||
Str::clear(parse);
|
||||
WRITE_TO(parse, "%S", mr.exp[0]);
|
||||
Str::trim_white_space(parse);
|
||||
C->default_allows = TRUE;
|
||||
negated = TRUE;
|
||||
}
|
||||
|
||||
if (Regexp::match(&mr, parse, L"for (%c+)")) {
|
||||
Str::clear(parse);
|
||||
WRITE_TO(parse, "%S", mr.exp[0]);
|
||||
Str::trim_white_space(parse);
|
||||
}
|
||||
|
||||
if (Str::eq(parse, I"all")) {
|
||||
if (negated) incorrect = TRUE; /* "not for all" */
|
||||
C->default_allows = TRUE;
|
||||
} else if (Str::eq(parse, I"none")) {
|
||||
if (negated) incorrect = TRUE; /* "not for none" */
|
||||
C->default_allows = FALSE;
|
||||
} else if (Compatibility::clause(C, parse) == FALSE)
|
||||
incorrect = TRUE;
|
||||
|
||||
DISCARD_TEXT(parse);
|
||||
Regexp::dispose_of(&mr);
|
||||
if (incorrect) C = NULL;
|
||||
return C;
|
||||
}
|
||||
|
||||
int Compatibility::clause(compatibility_specification *C, text_stream *text) {
|
||||
int correct = FALSE;
|
||||
match_results mr = Regexp::create_mr();
|
||||
if (Regexp::match(&mr, text, L"(%c+?), (%c+)")) {
|
||||
int a = Compatibility::clause(C, mr.exp[0]);
|
||||
int b = Compatibility::clause(C, mr.exp[1]);
|
||||
correct = a && b;
|
||||
} else if (Regexp::match(&mr, text, L"(%c+?) or (%c+)")) {
|
||||
int a = Compatibility::clause(C, mr.exp[0]);
|
||||
int b = Compatibility::clause(C, mr.exp[1]);
|
||||
correct = a && b;
|
||||
} else {
|
||||
inter_architecture *A = Architectures::from_codename(text);
|
||||
if (A) {
|
||||
int already_there = FALSE;
|
||||
inter_architecture *X;
|
||||
LOOP_OVER_LINKED_LIST(X, inter_architecture, C->exceptions)
|
||||
if (A == X)
|
||||
already_there = TRUE;
|
||||
if (already_there == FALSE) {
|
||||
ADD_TO_LINKED_LIST(A, inter_architecture, C->exceptions);
|
||||
correct = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
Regexp::dispose_of(&mr);
|
||||
return correct;
|
||||
}
|
||||
|
||||
int Compatibility::with(compatibility_specification *C, inter_architecture *A) {
|
||||
if (C == NULL) return FALSE;
|
||||
int decision = C->default_allows;
|
||||
inter_architecture *X;
|
||||
LOOP_OVER_LINKED_LIST(X, inter_architecture, C->exceptions)
|
||||
if (A == X)
|
||||
decision = decision?FALSE:TRUE;
|
||||
return decision;
|
||||
}
|
||||
|
||||
void Compatibility::test(OUTPUT_STREAM) {
|
||||
Compatibility::test_one(OUT, I"for all");
|
||||
Compatibility::test_one(OUT, I"all");
|
||||
Compatibility::test_one(OUT, I"not for all");
|
||||
Compatibility::test_one(OUT, I"not all");
|
||||
Compatibility::test_one(OUT, I"for none");
|
||||
Compatibility::test_one(OUT, I"none");
|
||||
Compatibility::test_one(OUT, I"not for none");
|
||||
Compatibility::test_one(OUT, I"not none");
|
||||
Compatibility::test_one(OUT, I"for 16d");
|
||||
Compatibility::test_one(OUT, I"not for 32");
|
||||
Compatibility::test_one(OUT, I"for 16d or 32d");
|
||||
Compatibility::test_one(OUT, I"not for 32 or 16");
|
||||
Compatibility::test_one(OUT, I"for 16d, 32d or 32");
|
||||
Compatibility::test_one(OUT, I"not for 16d, 32d or 32");
|
||||
}
|
||||
|
||||
void Compatibility::test_one(OUTPUT_STREAM, text_stream *test) {
|
||||
WRITE("'%S': ", test);
|
||||
compatibility_specification *C = Compatibility::from_text(test);
|
||||
if (C == NULL) { WRITE("not a valid compatibility specification\n"); return; }
|
||||
Compatibility::write(OUT, C);
|
||||
WRITE(":");
|
||||
inter_architecture *A;
|
||||
LOOP_OVER(A, inter_architecture)
|
||||
WRITE(" %S=%S", Architectures::to_codename(A),
|
||||
(Compatibility::with(C, A))?I"yes":I"no");
|
||||
WRITE("\n");
|
||||
}
|
12
inbuild/arch-module/Contents.w
Normal file
12
inbuild/arch-module/Contents.w
Normal file
|
@ -0,0 +1,12 @@
|
|||
Title: arch
|
||||
Author: Graham Nelson
|
||||
Purpose: Definitions of Inter and final VM architectures.
|
||||
Language: InC
|
||||
Licence: Artistic License 2.0
|
||||
|
||||
Chapter 1: Setting Up
|
||||
Arch Module
|
||||
|
||||
Chapter 2: Architectures
|
||||
Architectures
|
||||
Compatibility
|
|
@ -1,3 +1,5 @@
|
|||
{basics}
|
||||
|
||||
inbuild.mk
|
||||
|
||||
Tests/Units/_Results_Actual/
|
||||
|
|
|
@ -205,20 +205,22 @@ void Kits::construct_graph(inform_kit *K) {
|
|||
inbuild_copy *C = K->as_copy;
|
||||
pathname *P = C->location_if_path;
|
||||
build_vertex *KV = C->vertex;
|
||||
text_stream *archs[4] = { I"16", I"32", I"16d", I"32d" };
|
||||
text_stream *binaries[4] = { I"arch-16.interb", I"arch-32.interb", I"arch-16d.interb", I"arch-32d.interb" };
|
||||
build_vertex *BV[4];
|
||||
for (int i=0; i<4; i++) {
|
||||
filename *FV = Filenames::in_folder(P, binaries[i]);
|
||||
BV[i] = Graphs::file_vertex(FV);
|
||||
Graphs::need_this_to_build(KV, BV[i]);
|
||||
build_step *BS = BuildSteps::new_step(ASSIMILATE_BSTEP, P, archs[i]);
|
||||
BuildSteps::add_step(BV[i]->script, BS);
|
||||
linked_list *BVL = NEW_LINKED_LIST(build_vertex);
|
||||
inter_architecture *A;
|
||||
LOOP_OVER(A, inter_architecture) {
|
||||
build_vertex *BV = Graphs::file_vertex(Architectures::canonical_binary(P, A));
|
||||
Graphs::need_this_to_build(KV, BV);
|
||||
build_step *BS = BuildSteps::new_step(
|
||||
ASSIMILATE_BSTEP, P, Architectures::to_codename(A));
|
||||
BuildSteps::add_step(BV->script, BS);
|
||||
ADD_TO_LINKED_LIST(BV, build_vertex, BVL);
|
||||
}
|
||||
|
||||
filename *contents_page = Filenames::in_folder(C->location_if_path, I"Contents.w");
|
||||
build_vertex *CV = Graphs::file_vertex(contents_page);
|
||||
for (int i=0; i<4; i++) Graphs::need_this_to_build(BV[i], CV);
|
||||
build_vertex *BV;
|
||||
LOOP_OVER_LINKED_LIST(BV, build_vertex, BVL)
|
||||
Graphs::need_this_to_build(BV, CV);
|
||||
|
||||
kit_contents_section_state CSS;
|
||||
CSS.active = FALSE;
|
||||
|
@ -229,7 +231,9 @@ void Kits::construct_graph(inform_kit *K) {
|
|||
filename *SF = Filenames::in_folder(
|
||||
Pathnames::subfolder(C->location_if_path, I"Sections"), segment);
|
||||
build_vertex *SV = Graphs::file_vertex(SF);
|
||||
for (int i=0; i<4; i++) Graphs::need_this_to_build(BV[i], SV);
|
||||
build_vertex *BV;
|
||||
LOOP_OVER_LINKED_LIST(BV, build_vertex, BVL)
|
||||
Graphs::need_this_to_build(BV, SV);
|
||||
}
|
||||
|
||||
inbuild_requirement *req;
|
||||
|
|
|
@ -12,6 +12,7 @@ typedef struct inform_project {
|
|||
struct inform_language *language_of_play;
|
||||
struct inform_language *language_of_syntax;
|
||||
struct inform_language *language_of_index;
|
||||
int next_resource_number;
|
||||
MEMORY_MANAGEMENT
|
||||
} inform_project;
|
||||
|
||||
|
@ -25,6 +26,7 @@ inform_project *Projects::new_ip(text_stream *name, filename *F, pathname *P) {
|
|||
project->language_of_play = NULL;
|
||||
project->language_of_syntax = NULL;
|
||||
project->language_of_index = NULL;
|
||||
project->next_resource_number = 3;
|
||||
return project;
|
||||
}
|
||||
|
||||
|
@ -62,6 +64,22 @@ void Projects::not_necessarily_parser_IF(inform_project *project) {
|
|||
project->assumed_to_be_parser_IF = FALSE;
|
||||
}
|
||||
|
||||
@ Resources in a Blorb file have unique ID numbers which are positive integers,
|
||||
but these are not required to start from 1, nor to be contiguous. For Inform,
|
||||
ID number 1 is reserved for the cover image (whether or not any cover image
|
||||
is provided: it is legal for there to be figures but no cover, and vice versa).
|
||||
Other figures, and sound effects, then mix freely as needed from ID number 3
|
||||
on upwards. We skip 2 so that it can be guaranteed that no sound resource
|
||||
has ID 1 or 2: this is to help people trying to play sounds in the Z-machine,
|
||||
where operand 1 or 2 in the |@sound| opcode signifies not a sound resource
|
||||
number but a long or short beep. If a genuine sound effect had resource ID
|
||||
1 or 2, therefore, it would be unplayable on the Z-machine.
|
||||
|
||||
=
|
||||
int Projects::get_next_free_blorb_resource_ID(inform_project *project) {
|
||||
return project->next_resource_number++;
|
||||
}
|
||||
|
||||
void Projects::set_source_filename(inform_project *project, pathname *P, filename *F) {
|
||||
if (P) {
|
||||
filename *manifest = Filenames::in_folder(P, I"Contents.txt");
|
||||
|
|
|
@ -55,6 +55,7 @@ int Main::core_inform_main(int argc, char *argv[]) {
|
|||
IFModule::start();
|
||||
MultimediaModule::start();
|
||||
IndexModule::start();
|
||||
ArchModule::start();
|
||||
InterModule::start();
|
||||
BuildingModule::start();
|
||||
CodegenModule::start();
|
||||
|
@ -73,6 +74,7 @@ int Main::core_inform_main(int argc, char *argv[]) {
|
|||
IFModule::end();
|
||||
IndexModule::end();
|
||||
InterModule::end();
|
||||
ArchModule::end();
|
||||
BuildingModule::end();
|
||||
CodegenModule::end();
|
||||
InbuildModule::end();
|
||||
|
|
|
@ -16,6 +16,7 @@ Import: syntax
|
|||
Import: problems
|
||||
Import: linguistics
|
||||
Import: kinds
|
||||
Import: inbuild/arch
|
||||
Import: inter/inter
|
||||
Import: inbuild/inbuild
|
||||
Import: core
|
||||
|
|
|
@ -645,22 +645,3 @@ int VirtualMachines::compare_usage(const void *ent1, const void *ent2) {
|
|||
if (v2->bytes_used != v1->bytes_used) return v2->bytes_used - v1->bytes_used;
|
||||
return Wordings::first_wn(v1->structure_name) - Wordings::first_wn(v2->structure_name);
|
||||
}
|
||||
|
||||
@h Resource ID numbers.
|
||||
Resources in a Blorb file have unique ID numbers which are positive integers,
|
||||
but these are not required to start from 1, nor to be contiguous. For Inform,
|
||||
ID number 1 is reserved for the cover image (whether or not any cover image
|
||||
is provided: it is legal for there to be figures but no cover, and vice versa).
|
||||
Other figures, and sound effects, then mix freely as needed from ID number 3
|
||||
on upwards. We skip 2 so that it can be guaranteed that no sound resource
|
||||
has ID 1 or 2: this is to help people trying to play sounds in the Z-machine,
|
||||
where operand 1 or 2 in the |@sound| opcode signifies not a sound resource
|
||||
number but a long or short beep. If a genuine sound effect had resource ID
|
||||
1 or 2, therefore, it would be unplayable on the Z-machine.
|
||||
|
||||
=
|
||||
int next_free_resource_ID = 3;
|
||||
|
||||
int VirtualMachines::get_next_free_blorb_resource_ID(void) {
|
||||
return next_free_resource_ID++;
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ void PL::Figures::register_figure(wording F, wording FN) {
|
|||
|
||||
bf->name = F;
|
||||
if (wn >= 0) {
|
||||
bf->figure_number = VirtualMachines::get_next_free_blorb_resource_ID();
|
||||
bf->figure_number = Projects::get_next_free_blorb_resource_ID(Inbuild::project());
|
||||
TEMPORARY_TEXT(leaf);
|
||||
WRITE_TO(leaf, "%N", wn);
|
||||
bf->filename_of_image_file = Filenames::in_folder(pathname_of_materials_figures, leaf);
|
||||
|
|
|
@ -151,7 +151,7 @@ void PL::Sounds::register_sound(wording F, wording FN) {
|
|||
DISCARD_TEXT(leaf);
|
||||
|
||||
bs->name = F;
|
||||
bs->sound_number = VirtualMachines::get_next_free_blorb_resource_ID();
|
||||
bs->sound_number = Projects::get_next_free_blorb_resource_ID(Inbuild::project());
|
||||
bs->alt_description = <<alttext>>;
|
||||
|
||||
LOGIF(FIGURE_CREATIONS,
|
||||
|
|
|
@ -32,6 +32,7 @@ linked_list *requirements_list = NULL;
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
Foundation::start();
|
||||
ArchModule::start();
|
||||
InterModule::start();
|
||||
BuildingModule::start();
|
||||
CodegenModule::start();
|
||||
|
@ -70,22 +71,17 @@ int main(int argc, char **argv) {
|
|||
CommandLine::read(argc, argv, NULL, &Main::respond, &Main::add_file);
|
||||
|
||||
if (template_action == ASSIMILATE_CLSW) {
|
||||
text_stream *name = CodeGen::Architecture::leafname();
|
||||
if (Str::len(name) == 0) Errors::fatal("no -architecture given");
|
||||
inter_architecture *A = CodeGen::Architecture::current();
|
||||
if (A == NULL) Errors::fatal("no -architecture given");
|
||||
filename *assim = Architectures::canonical_binary(template_path, A);
|
||||
filename *assim_t = Architectures::canonical_textual(template_path, A);
|
||||
pipeline_as_file = Filenames::in_folder(path_to_pipelines, I"assimilate.interpipeline");
|
||||
TEMPORARY_TEXT(leafname);
|
||||
WRITE_TO(leafname, "%S.interb", name);
|
||||
filename *assim = Filenames::in_folder(template_path, leafname);
|
||||
TEMPORARY_TEXT(fullname);
|
||||
WRITE_TO(fullname, "%f", assim);
|
||||
Str::copy(Dictionaries::create_text(pipeline_vars, I"*out"), fullname);
|
||||
Str::clear(leafname);
|
||||
Str::clear(fullname);
|
||||
WRITE_TO(leafname, "%S.intert", name);
|
||||
filename *assim_t = Filenames::in_folder(template_path, leafname);
|
||||
WRITE_TO(fullname, "%f", assim_t);
|
||||
Str::copy(Dictionaries::create_text(pipeline_vars, I"*outt"), fullname);
|
||||
DISCARD_TEXT(leafname);
|
||||
DISCARD_TEXT(fullname);
|
||||
match_results mr = Regexp::create_mr();
|
||||
Str::copy(Dictionaries::create_text(pipeline_vars, I"*attach"), Pathnames::directory_name(template_path));
|
||||
|
@ -97,6 +93,7 @@ int main(int argc, char **argv) {
|
|||
InterModule::end();
|
||||
BuildingModule::end();
|
||||
CodegenModule::end();
|
||||
ArchModule::end();
|
||||
Foundation::end();
|
||||
|
||||
if (Errors::have_occurred()) return 1;
|
||||
|
|
|
@ -8,6 +8,7 @@ Version Name: Axion
|
|||
|
||||
Import: foundation
|
||||
Import: inform7/words
|
||||
Import: inbuild/arch
|
||||
Import: inter
|
||||
Import: building
|
||||
Import: codegen
|
||||
|
|
|
@ -2,36 +2,18 @@
|
|||
|
||||
To deal with multiple inter architectures.
|
||||
|
||||
@h Architectures.
|
||||
These are simply enumerated, for now.
|
||||
|
||||
@e NO_ARCHITECTURE from 0
|
||||
@e A_16_ARCHITECTURE
|
||||
@e A_16D_ARCHITECTURE
|
||||
@e A_32_ARCHITECTURE
|
||||
@e A_32D_ARCHITECTURE
|
||||
@h Current architecture.
|
||||
|
||||
=
|
||||
int current_architecture = NO_ARCHITECTURE;
|
||||
inter_architecture *current_architecture = NULL;
|
||||
int CodeGen::Architecture::set(text_stream *name) {
|
||||
int setting = NO_ARCHITECTURE;
|
||||
if (Str::eq_insensitive(name, I"16")) setting = A_16_ARCHITECTURE;
|
||||
if (Str::eq_insensitive(name, I"32")) setting = A_32_ARCHITECTURE;
|
||||
if (Str::eq_insensitive(name, I"16d")) setting = A_16D_ARCHITECTURE;
|
||||
if (Str::eq_insensitive(name, I"32d")) setting = A_32D_ARCHITECTURE;
|
||||
if (setting == NO_ARCHITECTURE) return FALSE;
|
||||
current_architecture = setting;
|
||||
return TRUE;
|
||||
current_architecture = Architectures::from_codename(name);
|
||||
if (current_architecture) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
text_stream *CodeGen::Architecture::leafname(void) {
|
||||
switch (current_architecture) {
|
||||
case A_16_ARCHITECTURE: return I"arch-16";
|
||||
case A_16D_ARCHITECTURE: return I"arch-16d";
|
||||
case A_32_ARCHITECTURE: return I"arch-32";
|
||||
case A_32D_ARCHITECTURE: return I"arch-32d";
|
||||
}
|
||||
return NULL;
|
||||
inter_architecture *CodeGen::Architecture::current(void) {
|
||||
return current_architecture;
|
||||
}
|
||||
|
||||
@h Prepare stage.
|
||||
|
@ -42,14 +24,10 @@ void CodeGen::Architecture::create_pipeline_stage(void) {
|
|||
}
|
||||
|
||||
int CodeGen::Architecture::run_prepare_stage(pipeline_step *step) {
|
||||
switch (current_architecture) {
|
||||
case NO_ARCHITECTURE: internal_error("no architecture set");
|
||||
case A_16_ARCHITECTURE: return CodeGen::Architecture::run_prepare_stage_inner(step, TRUE, FALSE);
|
||||
case A_16D_ARCHITECTURE: return CodeGen::Architecture::run_prepare_stage_inner(step, TRUE, TRUE);
|
||||
case A_32_ARCHITECTURE: return CodeGen::Architecture::run_prepare_stage_inner(step, FALSE, FALSE);
|
||||
case A_32D_ARCHITECTURE: return CodeGen::Architecture::run_prepare_stage_inner(step, FALSE, TRUE);
|
||||
}
|
||||
return FALSE;
|
||||
if (current_architecture == NULL) internal_error("no architecture set");
|
||||
return CodeGen::Architecture::run_prepare_stage_inner(step,
|
||||
Architectures::sixteen_bit(current_architecture),
|
||||
Architectures::debug_enabled(current_architecture));
|
||||
}
|
||||
|
||||
int CodeGen::Architecture::run_prepare_stage_inner(pipeline_step *step, int Z, int D) {
|
||||
|
|
|
@ -29,11 +29,10 @@ void CodeGen::LinkInstructions::create_pipeline_stage(void) {
|
|||
int CodeGen::LinkInstructions::run_link_stage(pipeline_step *step) {
|
||||
link_instruction *req;
|
||||
LOOP_OVER_LINKED_LIST(req, link_instruction, step->requirements_list) {
|
||||
TEMPORARY_TEXT(leafname);
|
||||
WRITE_TO(leafname, "%S.interb", CodeGen::Architecture::leafname());
|
||||
filename *arch_file = Filenames::in_folder(req->location, leafname);
|
||||
inter_architecture *A = CodeGen::Architecture::current();
|
||||
if (A == NULL) Errors::fatal("no -architecture given");
|
||||
filename *arch_file = Architectures::canonical_binary(req->location, A);
|
||||
if (TextFiles::exists(arch_file) == FALSE) internal_error("no arch file for requirement");
|
||||
DISCARD_TEXT(leafname);
|
||||
|
||||
inter_tree *sidecar = Inter::Tree::new();
|
||||
if (Inter::Binary::test_file(arch_file)) Inter::Binary::read(sidecar, arch_file);
|
||||
|
|
|
@ -61,6 +61,7 @@ INBUILDX = inbuild/Tangled/inbuild
|
|||
{module} INTER inter inter/inter-module
|
||||
{module} BUILDING building inter/building-module
|
||||
{module} CODEGEN codegen inter/codegen-module
|
||||
{module} ARCH arch inbuild/arch-module
|
||||
{module} INBUILD inbuild inbuild/inbuild-module
|
||||
|
||||
# First, the tools we need to make, using the same declaration notation.
|
||||
|
@ -87,6 +88,7 @@ INBUILDX = inbuild/Tangled/inbuild
|
|||
{dep} INFORM7 on IF
|
||||
{dep} INFORM7 on MULTIMEDIA
|
||||
{dep} INFORM7 on INDEX
|
||||
{dep} INFORM7 on ARCH
|
||||
{dep} INFORM7 on INTER
|
||||
{dep} INFORM7 on BUILDING
|
||||
{dep} INFORM7 on CODEGEN
|
||||
|
@ -101,10 +103,12 @@ INBUILDX = inbuild/Tangled/inbuild
|
|||
{tool} INBUILDTOOL inbuild inbuild
|
||||
{dep} INBUILDTOOL on FOUNDATION
|
||||
{dep} INBUILDTOOL on WORDS
|
||||
{dep} INBUILDTOOL on ARCH
|
||||
{dep} INBUILDTOOL on INBUILD
|
||||
|
||||
{tool} INTERTOOL inter inter
|
||||
{dep} INTERTOOL on FOUNDATION
|
||||
{dep} INTERTOOL on ARCH
|
||||
{dep} INTERTOOL on INTER
|
||||
{dep} INTERTOOL on BUILDING
|
||||
{dep} INTERTOOL on CODEGEN
|
||||
|
|
Loading…
Reference in a new issue