Fil-C on Nix

Filnix wiki

mbrock/filnix/nanofil

nfb.pl

NFB, the nanofil bytecode: a module of ir.pl written as little-endian 32-bit words in a sectioned container, and read back (docs/nfb.md). The encoding is a function of the module, and the reader accepts only its image, so the words are the module's identity.

One table, nfb_form/3, states every instruction: its opcode, its term with the parts as variables, and the fields its words hold in order. The writer reads the table with the term given, the reader with the opcode given, so the two directions cannot disagree about a layout. module_nfb/2 is the relation between a module and its words; it runs either way, and its reading checks that writing the module gives the very words it read.

The container

WordsHold
headermagic 0x0042464E, version, flags (stage, mode, ordered), section count
STRINGS (1)symbol names and loc files, sorted bytes
CONSTANTS (2)constants an operand word cannot hold, sorted, 3 words each
SYMBOLS (3)defined symbols in item order, then the named-only sorted
DATA (4), FUNCTIONS (5)the data objects and the function bodies, in symbol order
NAMES (0x100)the names of temporaries, labels and locals, as terms
CONTEXT (0x101)the context/2 items and where they stood

Ids

A temporary's id is its place among the function's first definitions: the parameters, then each definition in stream order. A later definition of the same temporary (ir.pl's IR is not strict SSA) is preceded by a rebind word naming its id. Blocks and named locals are numbered in stream order. Without NAMES, the reader names each by its id, an integer.

useslists
usesassoc
usesdcgs
usesirmodule_mode/2, module_stage/2

The table

nfb_code?Enum, ?Term, ?Codenondet

Code is the word that stands for Term in a field of enumeration Enum. Classes and widths share codes, so that a store's width and a load's type read like the class they hold.

51nfb_codeclass, w, 1
51nfb_codeclass, l, 2
51nfb_codeclass, s, 3
52nfb_codeclass, d, 4
52nfb_codeclass, x, 5
52nfb_codeclass, p, 6
53nfb_codeclass, a, 7
53nfb_codeclass, f, 8
54nfb_codewidth, W, C ←
nfb_codeclass, W, C
C ≤ 6
55nfb_codewidth, b, 9
55nfb_codewidth, h, 10
56nfb_codeload, T, C ←
memberT, l, s, d, x, p
nfb_codeclass, T, C
57nfb_codeload, T, C ←
58nfb_codeext, T, C ←
memberT, s, d
nfb_codeclass, T, C
59nfb_codeext, T, C ←
60nfb_codecas, T, C ←
memberT, l, p
nfb_codeclass, T, C
61nfb_codecas, T, C ←
62nfb_codecond, Cond, C ←
nth0C, eq, ne, sle, slt, sge, sgt, ule, ult, uge, ugt, le, lt, ge, gt, o, uo, Cond
64nfb_coderights, read, 0
64nfb_coderights, write, 1
65nfb_codebound, upper, 0
65nfb_codebound, lower, 1
66nfb_codesetjmp, setjmp, 0
66nfb_codesetjmp, '_setjmp', 1
66nfb_codesetjmp, sigsetjmp, 2
67nfb_codeeffect, E, C ←
nth0C, aux_read, lower_resolve, address_read, aux_ensure, lower_barrier, rooted_reload, lower_write, address_write, atomic_read, atomic_write, atomic_cas, E
71nfb_codeflight, copy, 0
71nfb_codeflight, add, 1
71nfb_codeflight, sub, 2
72nfb_codemnemonic, M, C ←
nth0C, cpuid, xgetbv, rdtsc, rdtscp, lfence, sfence, pause, M
74nfb_coderegister, R, C ←
nth0C, a, b, c, d, R
75nfb_codefunc_linkage, L, C ←
nth0C, export, local, weak, L
76nfb_codedata_linkage, L, C ←
nth0C, export, local, weak, roexport, rolocal, roweak, tlsexport, tlslocal, initctor, priority, initdtor, priority, initctor, none, initdtor, none, externweak, L
80nfb_codealias_linkage, export, 0
80nfb_codealias_linkage, weak, 2
82narrow_codeT, C ←
nth0I, sw, uw, sh, uh, sb, ub, T
C is 16 + I
nfb_form?Opcode, ?Term, ?Fieldsnondet

The instruction, phi or jump Term is written as the header word of Opcode, then Fields in order. Each field names a part of Term:

FieldWords
defDnone: tmpD takes the next temporary id
classK, enumE, Xone code (nfb_code/3)
u32N, i64NN as one word, or as two (low, high), signed
opndVan operand word: a temporary, constant or symbol
labelL, targetTa block index; for a target shifted left, bit 0 for poll
localX, local_defXa local's id; the definition writes none
strAa STRINGS id
resultRa call's result word, defining its temporaries
altX, Altsa tag word, then the fields of the alternative Tag-X-Fields
countXs, X, Fsthe length of Xs, then Fs for each element X
restXs, X, FsFs for each element X, to the instruction's end

Each opcode belongs to one group: 1 is the rebind prefix, 8 the phi, 0x10 to 0x7F plain instructions and 0x80 to 0x8F jumps.

105nfb_form0x08, phitmpD, K, Ps, defD, classK, restPs, L−V, labelL, opndV
106nfb_formCode, lettmpD, K, Op, A, B, defD, classK, opndA, opndB ←
binary_opCode, Op
108nfb_formCode, lettmpD, K, Op, A, defD, classK, opndA ←
unary_opCode, Op
110nfb_form0x38, lettmpD, K, cmpC, K1, A, B, defD, classK, enumcond, C, classK1, opndA, opndB
112nfb_form0x39, lettmpD, K, extT, A, defD, classK, enumext, T, opndA
113nfb_form0x3A, lettmpD, K, loadT, A, defD, classK, enumload, T, opndA
114nfb_form0x3B, lettmpD, K, allocAl, A, defD, classK, u32Al, opndA
115nfb_form0x3C, lettmpD, K, va_args, A, defD, classK, opndA
116nfb_form0x3D, lettmpD, K, va_arg, A, defD, classK, opndA
117nfb_form0x3E, lettmpD, K, setjmpJ, A, B, defD, classK, enumsetjmp, J, opndA, opndB
119nfb_form0x3F, lettmpD, K, atomic_loadp, A, defD, classK, opndA
120nfb_form0x40, lettmpD, K, casT, A, B, C, defD, classK, enumcas, T, opndA, opndB, opndC
122nfb_form0x50, lettmpD, K, checkLo, Hi, R, Al, P, defD, classK, i64Lo, i64Hi, enumrights, R, u32Al, opndP
124nfb_form0x51, lettmpD, K, check_aheadLo, Hi, R, Al, AHi, P, defD, classK, i64Lo, i64Hi, enumrights, R, u32Al, i64AHi, opndP
126nfb_formCode, lettmpD, K, Op, A, B, defD, classK, i64Lo, i64Hi, enumrights, R, u32Al, opndA, opndB ←
range_opCode, Op, Lo, Hi, R, Al
129nfb_form0x53, lettmpD, K, renew_hullLo, Hi, R, Al, A, B, C, defD, classK, i64Lo, i64Hi, enumrights, R, u32Al, opndA, opndB, opndC
131nfb_form0x54, lettmpD, K, half_checkBd, Lo, Hi, R, Al, A, B, defD, classK, enumbound, Bd, i64Lo, i64Hi, enumrights, R, u32Al, opndA, opndB
134nfb_form0x55, lettmpD, K, span_testLo, Hi, P, defD, classK, i64Lo, i64Hi, opndP
135nfb_form0x57, lettmpD, K, limitSize, P, defD, classK, u32Size, opndP
136nfb_form0x59, lettmpD, K, check_localX, Off, Bytes, R, Al, [], defD, classK, localX, i64Off, i64Bytes, enumrights, R, u32Al
138nfb_form0x5A, lettmpD, K, check_function, P, defD, classK, opndP
139nfb_form0x5B, lettmpD, K, raw_loadT, Off, A, defD, classK, enumload, T, i64Off, opndA
141nfb_form0x5C, lettmpD, K, raw_load_pointerOff, Es, A, defD, classK, i64Off, opndA, restEs, E, enumeffect, E
143nfb_form0x5D, lettmpD, K, raw_casT, Off, A, B, C, defD, classK, enumcas, T, i64Off, opndA, opndB, opndC
145nfb_form0x60, storeW, V, A, enumwidth, W, opndV, opndA
146nfb_form0x61, atomic_storep, V, A, opndV, opndA
147nfb_form0x62, fence, []
148nfb_form0x63, accessR, A, Size, Al, enumrights, R, u32Size, u32Al, opndA
149nfb_form0x64, local_allocX, Size, local_defX, i64Size
150nfb_form0x65, local_loadtmpD, K, T, X, Off, defD, classK, enumload, T, localX, i64Off
152nfb_form0x66, local_storeW, V, X, Off, enumwidth, W, localX, i64Off, opndV
153nfb_form0x67, callRes, F, Args, resultRes, opndF, restArgs, argK, V, classK, opndV
154nfb_form0x68, asm_fixedM, Ins, Outs, enummnemonic, M, countIns, R−V, enumregister, R, opndV, restOuts, R1−tmpD, enumregister, R1, defD
157nfb_form0x69, locFile, Line, strFile, u32Line
158nfb_form0x70, touchV, opndV
159nfb_form0x71, raw_callRes, F, Args, resultRes, opndF, restArgs, argK, V, classK, opndV
161nfb_form0x72, flighttmpD, Op, Args, Lower, defD, enumflight, Op, altLower, 0−none−[], 1−lowerP−opndP, restArgs, X, altX, 1−addressQ−opndQ, 0−V−opndV
164nfb_form0x73, raw_storeW, Off, V, A, enumwidth, W, i64Off, opndV, opndA
165nfb_form0x74, raw_store_pointerOff, V, A, Es, i64Off, opndV, opndA, restEs, E, enumeffect, E
167nfb_form0x80, gotoT, targetT
168nfb_form0x81, branchV, T1, T2, opndV, targetT1, targetT2
169nfb_form0x82, retV, opndV
170nfb_form0x83, retsVs, restVs, V, opndV
171nfb_form0x84, ret, []
172nfb_form0x85, unreachable, []
174binary_opCode, Op ←
nth0I, add, sub, mul, div, udiv, rem, urem, and, or, xor, sar, shr, shl, Op
Code is 0x10 + I
177unary_opCode, Op ←
nth0I, neg, copy, cast, truncd, truncx, ptoi, itop, stosi, stoui, dtosi, dtoui, xtosi, xtoui, swtof, uwtof, sltof, ultof, sqrt, Op
Code is 0x20 + I
range_op
1810x52renewLo, Hi, R, AlLoHiRAl
1820x56renew_ifLo, Hi, R, AlLoHiRAl
1830x58check_limitLo, Hi, R, AlLoHiRAl
185rebind_opcode0x01
group+Opcode, ?Group

phi, plain or jump.

188groupC, G ←
G = G0
189opcode_group0x08, phi ←
!
190opcode_groupC, jump ←
C ≥ 0x80
!
191opcode_group_, plain

The relation

195magic0x0042464E
196version0x00000001
module_nfb?Module, ?Wordssemidet

Words is the NFB of Module, NAMES and CONTEXT included. With Module ground it writes; otherwise it reads Words, and fails unless they are exactly what writing the module they decode to gives. Throws nanofil_error(Msg) for a module that has no encoding.

204module_nfbM, Ws ←
groundM
→
module_nfbM, names, context, Ws
is_listWs
maplistinteger, Ws
→
module_nfb+Module, +Sides, -Wordsdet

Words is the NFB of Module with the side sections Sides, a subset of [names, context].

213module_nfbmoduleAll, Sides, Ws ←
partition_itemsAll, 0, Items, Contexts
T = tablesStrs, Consts, Syms, _, _, _
phrasefuncsItems, T, true, Ordered, NameRecs, FuncWs
phrasedata_objectsItems, T, DataWs
phrasesymbols_wordsSyms, T, SymWs
phrasestrings_wordsStrs, StrWs
phraseconstants_wordsConsts, ConstWs
Core = 1−StrWs−Strs, 2−ConstWs−Consts, 3−SymWs−Syms, 4−DataWs−DataWs, 5−FuncWs−FuncWs
memberchknames, Sides
NameRecs ≢ []
→
names_wordsNameRecs, NamesWs
Side1 = 0x100−NamesWs
else
Side1 = []
memberchkcontext, Sides
Contexts ≢ []
→
context_wordsContexts, CtxWs
Side2 = 0x101−CtxWs
else
Side2 = []
findallId−Ws1,
memberId−Ws1−Tab, Core
Tab ≢ []
,
CoreSecs
appendCoreSecs, Side1, Secs0
appendSecs0, Side2, Secs
lengthSecs, NSecs
module_stagemoduleItems, Stage
module_modemoduleItems, Mode
flagsStage, Mode, Ordered, Flags
magicMagic
versionVersion
phrasesectionsSecs, SecWs
Ws = Magic, Version, Flags, NSecs|SecWs
238flagsStage, Mode, Ordered, Flags ←
Stage ≡ checked
→
S = 1
else
S = 0
Mode ≡ filc
→
F = 2
else
F = 0
Ordered ≡ true
→
O = 4
else
O = 0
Flags is S \/ F \/ O
244sections[] ⟶
[]
245sectionsId−Ws|Ss ⟶
lengthWs, N
Id, N
seqWs
nfb_core+Words, -Coredet

Core is the NFB Words without its side sections: the words the module's identity is taken over.

251nfb_coreWs, Core ←
sections_below0x100, Ws, Core
sections_below+Limit, +Ws, -Ws1

Ws with only its sections of ids below Limit.

255sections_belowLimit, Magic, Version, Flags, _|SecWs, Magic, Version, Flags, N|Ws ←
split_sectionsSecWs, Secs
secs_belowSecs, Limit, Kept
lengthKept, N
phrasesectionsKept, Ws
260secs_below[], _, []
261secs_belowId−Ws|Ss, Limit, Kept ←
Id < Limit
→
Kept = Id−Ws|Kept1
else
Kept = Kept1
secs_belowSs, Limit, Kept1
265split_sections[], []
266split_sectionsId, N|Ws0, Id−Ws|Ss ←
phrasetakeN, Ws, Ws0, Ws1
!
partition_items+All, +I, -Items, -Contexts

the context items of All, each with the number of other items before it, and the rest.

272partition_items[], _, [], []
273partition_itemsC|Is, I, Items, I−C|Cs ←
C = context_, _
!
partition_itemsIs, I, Items, Cs
275partition_itemsIt|Is, I, It|Items, Cs ←
I1 is I + 1
partition_itemsIs, I1, Items, Cs

Tables: strings, constants and symbols

module_tables+Items, -Tables

tables(Strs, Consts, Syms, SymIds, StrIds, ConstIds), each Ids an assoc from a name or constant to its id. Syms lists sym(Name, Kind, Item): the defined symbols in item order, then the named-only by name.

282module_tablesItems, tablesStrs, Consts, Syms, SymIds, StrIds, ConstIds ←
findallsymN, Kind, It,
memberIt, Items
item_symbolIt, N, Kind
,
Defined
findallN, membersymN, _, _, Defined, DefNames
findallP,
memberIt, Items
,
Parts0
sortParts0, Parts
findallN−t, memberN, DefNames, Ds0
sortDs0, Ds
list_to_assocDs, DefSet
findallS,
memberglobalS, Parts
¬get_assocS, DefSet, _
,
Named0
maplistmust_atom, DefNames
maplistmust_atom, Named0
sort_by_bytesNamed0, Named
findallsymN, named, none, memberN, Named, NamedSyms
appendDefined, NamedSyms, Syms
first_idsSyms, 0, [], SymPairs
list_to_assocSymPairs, SymIds
findallF, memberfileF, Parts, Files
maplistmust_atom, Files
appendDefNames, Named, SymNames
appendSymNames, Files, Strs0
sortStrs0, Strs1
sort_by_bytesStrs1, Strs
numberedStrs, 0, StrPairs
list_to_assocStrPairs, StrIds
findallC,
memberconstC, Parts
,
Cs0
maplistmust_wide, Cs0
sortCs0, Consts
numberedConsts, 0, CPairs
list_to_assocCPairs, ConstIds
305must_wideN ←
integerN
N ≥ −1 << 95
N < 1 << 95
!
306must_wideN ←
nfb_error'~q does not fit in 96 bits', N
first_ids+Syms, +I, +Seen, -Pairs

each name's first symbol id.

309first_ids[], _, Ps0, Ps ←
sortPs0, Ps1
first_keysPs1, Ps
310first_idssymN, _, _|Ss, I, Ps0, Ps ←
I1 is I + 1
first_idsSs, I1, N−I|Ps0, Ps
311first_keys[], []
312first_keysK−V|Ps, K−V|Qs ←
drop_keyK, Ps, Ps1
first_keysPs1, Qs
313drop_keyK, K1−_|Ps, Qs ←
K1 ≡ K
!
drop_keyK, Ps, Qs
314drop_key_, Ps, Ps
316numbered[], _, []
317numberedX|Xs, I, X−I|Ps ←
I1 is I + 1
numberedXs, I1, Ps
319must_atomA ←
atomA
!
320must_atomA ←
nfb_error'a symbol or file name must be an atom: ~q', A
322sort_by_bytesAs, Sorted ←
findallBs−A,
memberA, As
,
Ps0
msortPs0, Ps
pairs_values_Ps, Sorted
325pairs_values_[], []
326pairs_values__−V|Ps, V|Vs ←
item_symbol
328funcN, _, _, _, _Nfunc
329dataN, _, _, _Ndata
330aliasN, _, _Nalias
item_part+Item, -Part

the item refers to the symbol of global(S), uses the constant const(N) or the file file(F), as its forms say.

334item_partfunc_, _, _, _, Bs, P ←
memberblock_, Phis, Insts, J, Bs
memberI, Phis
or
memberI, Insts
or
I = J
form_ofI, _, Fields
phrasefpartsFields, Ps
memberP, Ps
338item_partdata_, _, _, Its, P ←
memberIt, Its
It = item_, symS, _
P = globalS
or
It = item_, constN
P = constN
340item_partalias_, _, S, globalS
342fparts[] ⟶
[]
343fpartsF|Fs ⟶
344fpartopndV ⟶
!
V = global_
or
V = const_
→
V
else
[]
345fpartstrA ⟶
!
fileA
346fpartrestXs, X, Fs ⟶
!
elems_partsXs, X, Fs
347fpartcountXs, X, Fs ⟶
!
elems_partsXs, X, Fs
348fpartaltX, Alts ⟶
!
member_−X1−Fs, Alts
copy_termX1−Fs, X−Fs1
→
true
else
Fs1 = []
349fpart_ ⟶
[]
350elems_parts[], _, _ ⟶
[]
351elems_partsE|Es, X, Fs ⟶
copy_termX−Fs, E−Fs1
→
true
else
Fs1 = []
elems_partsEs, X, Fs
353inline_constN ←
integerN
N ≥ −1 << 29
N < 1 << 29
355strings_words[] ⟶
!
356strings_wordsStrs ⟶
lengthStrs, N
N
357strings[] ⟶
[]
358stringsA|As ⟶
360constants_words[] ⟶
!
361constants_wordsCs ⟶
lengthCs, N
N
362wides[] ⟶
[]
363widesC|Cs ⟶
365symbols_words[], _ ⟶
!
366symbols_wordsSyms, T ⟶
lengthSyms, N
N
symbolsSyms, T
367symbols[], _ ⟶
[]
368symbolsS|Ss, T ⟶
symbolS, T
symbolsSs, T
370symbolsymN, Kind, It, T ⟶
T = tables_, _, _, SymIds, StrIds, _
get_assocN, StrIds, Sid
symbol_kindKind, It, SymIds, K, L, Extra
W is K \/ L << 8
Sid, W, Extra
376symbol_kindfunc, func_, Lk, _, _, _, _, 0, L, 0 ←
linkage_codefunc_linkage, Lk, L
377symbol_kinddata, data_, Lk, _, _, _, 1, L, Extra ←
Lk = initW, P
integerP
→
linkage_codedata_linkage, initW, priority, L
Extra = P
else
linkage_codedata_linkage, Lk, L
Extra = 0
381symbol_kindalias, alias_, Lk, Tg, SymIds, 2, L, Extra ←
linkage_codealias_linkage, Lk, L
get_assocTg, SymIds, Extra
→
true
else
nfb_error'no symbol ~q', Tg
384symbol_kindnamed, _, _, 3, 0, 0

A priority stands for the integer in the symbol's extra word.

387linkage_codeE, Lk, C ←
Lk ≠ init_, priority
nfb_codeE, Lk, C
!
388linkage_codeE, initW, priority, C ←
!
nfb_codeE, initW, priority, C
389linkage_codeE, Lk, _ ←
nfb_error'no ~w code for ~q', E, Lk

Data

393data_objects[], _ ⟶
[]
394data_objectsdata_, _, Al, Its|Is, T ⟶
!
lengthIts, N
Al, N
396data_objects_|Is, T ⟶
398data_items[], _ ⟶
[]
399data_itemsIt|Its, T ⟶
401data_itemitemb, strCs, _ ⟶
!
maplistchar_byte, Cs, Bs
1
402data_itemitemW, constN, T ⟶
!
0
codewidth, W
403data_itemitemW, symS, Off, T ⟶
!
memberchkW, l, p
T = tables_, _, _, SymIds, _, _
get_assocS, SymIds, Sid
2
codewidth, W
Sid
i64Off
406data_itemzeroN, _ ⟶
!
3
407data_itemIt, _ ⟶
nfb_error'no encoding for the data item ~q', It
409char_byteC, B ←
atomC
atom_lengthC, 1
char_codeC, B
B ≤ 255
!
410char_byteC, _ ←
nfb_error'a str/1 element is not a byte: ~q', C

Functions

funcs+Items, +T, +O0, -O, -NameRecs//

the FUNCTIONS payload; O is true when O0 is and every body is ordered, and NameRecs the names of each function's temporaries, labels and locals.

417funcs[], _, O, O, [] ⟶
[]
418funcsfuncN, _, Ret, Ps, Bs|Is, T, O0, O, Rec|Recs ⟶
!
catchbody_wordsRet, Ps, Bs, T, BodyWs, O1, Rec, nanofil_errorMsg,
formatatomMsg1, '~w: ~w', N, Msg
thrownanofil_errorMsg1
lengthBodyWs, L
O1 ≡ true
→
O2 = O0
else
O2 = false
L
seqBodyWs
funcsIs, T, O2, O, Recs
425funcs_|Is, T, O0, O, Recs ⟶
funcsIs, T, O0, O, Recs

fctx(Temps, Labels, Locals, Tables): a function's ids, assocs from each name to its id.

429body_wordsRet, Ps, Bs, T, Ws, Ordered, namesTempNames, Labels, LocalNames ←
func_idsPs, Bs, Temps, NT, TempNames, Labels, LabelIds, Locals, NL, LocalNames
lengthPs, NP
lengthBs, NB
Ctx = fctxTemps, LabelIds, Locals, T
maplistparam_class, Ps, PKs
phraseblocksBs, 0, Ctx, NP, _, true, Ordered, Stream
phrase
NP
seqPKs
NB, NT, NL
seqStream
,
Ws
437param_classparamK, tmp_, C ←
memberchkK, w, l, p, s, d
nfb_codeclass, K, C
!
438param_classP, _ ←
nfb_error'no encoding for the parameter ~q', P
440ret_wordvoid ⟶
!
0
441ret_worddata ⟶
!
15
442ret_wordtupleK1, K2 ⟶
!
nfb_codeclass, K1, C1
nfb_codeclass, K2, C2
W is 0x100 + 16 × C1 + C2
W
443ret_wordK ⟶
nfb_codeclass, K, C
!
C
444ret_wordR ⟶
nfb_error'no encoding for the return type ~q', R
func_ids...

each temporary's id by first definition, each label's block index and each local's id, and the names in id order.

448func_idsPs, Bs, Temps, NT, TempNames, Labels, LabelIds, Locals, NL, LocalNames ←
findallD, memberparam_, tmpD, Ps, PDs
findallD,
memberblock_, Phis, Insts, _, Bs
memberI, Phis
or
memberI, Insts
,
BDs
appendPDs, BDs, Ds
lengthPDs, NP
sortPDs, SPDs
lengthSPDs, NSP
NSP =:= NP
→
true
else
nfb_error'two parameters share a name', []
first_defsDs, TempNames
lengthTempNames, NT
numberedTempNames, 0, TPs
list_to_assocTPs, Temps
findallL, memberblockL, _, _, _, Bs, Labels
uniqueLabels, label
numberedLabels, 0, LPs
list_to_assocLPs, LabelIds
findallX,
memberblock_, _, Insts, _, Bs
memberlocal_allocX, _, Insts
,
LocalNames
uniqueLocalNames, local
lengthLocalNames, NL
numberedLocalNames, 0, XPs
list_to_assocXPs, Locals
464uniqueXs, What ←
msortXs, S
sortXs, U
lengthS, N
lengthU, M
N =:= M
→
true
else
nfb_error'two ~ws share a name', What
first_defs+Ds, -Firsts

Ds without the repeats, first occurrence kept.

469first_defsDs, Firsts ←
first_defsDs, t, Firsts
470first_defs[], _, []
471first_defsD|Ds, Seen0, Fs ←
Seen0 ≢ t
get_assocD, Seen0, _
→
Fs = Fs1
Seen = Seen0
else
Seen0 ≡ t
→
empty_assocE
else
E = Seen0
put_assocD, E, x, Seen
Fs = D|Fs1
first_defsDs, Seen, Fs1
inst_defs+Inst, -D

D is a temporary Inst defines, in order.

478inst_defsI, D ←
form_ofI, _, Fields
field_defsFields, Ds
memberD, Ds
481form_ofI, Code, Fields ←
nfb_formCode, I, Fields
→
true
else
nfb_error'no encoding for ~q', I
486field_defsFs, Ds ←
phrasefdefsFs, Ds
487fdefs[] ⟶
[]
488fdefsF|Fs ⟶
489fdefdefD ⟶
!
D
490fdefresultR ⟶
491fdefrestXs, X, Fs ⟶
!
elems_defsXs, X, Fs
492fdefcountXs, X, Fs ⟶
!
elems_defsXs, X, Fs
493fdefaltX, Alts ⟶
!
member_−X1−Fs, Alts
copy_termX1−Fs, X−Fs1
→
true
else
Fs1 = []
494fdef_ ⟶
[]
495elems_defs[], _, _ ⟶
[]
496elems_defsE|Es, X, Fs ⟶
copy_termX−Fs, E−Fs1
→
true
else
Fs1 = []
elems_defsEs, X, Fs
497result_defsvoid ⟶
[]
498result_defsresulttmpD, _ ⟶
D
499result_defstupleRs ⟶
findallD, memberresulttmpD, _, Rs, Ds
seqDs
blocks+Bs, +I, +Ctx, +N0, -N, +O0, -O//

the stream of the blocks from index I, N0 temporaries defined before them, O whether ordered.

503blocks[], _, _, N, N, O, O ⟶
[]
504blocksblock_, Phis, Insts, J|Bs, I, Ctx, N0, N, O0, O ⟶
I =:= 0
Phis ≢ []
→
nfb_error'the entry block has phis', []
else
[]
instsPhis, phi, I, Ctx, N0, N1, O0, O1
instsInsts, plain, I, Ctx, N1, N2, O1, O2
instsJ, jump, I, Ctx, N2, N3, O2, O3
I1 is I + 1
blocksBs, I1, Ctx, N3, N, O3, O
512insts[], _, _, _, N, N, O, O ⟶
[]
513instsX|Xs, G, B, Ctx, N0, N, O0, O ⟶
instX, G, B, Ctx, N0, N1, O0, O1
instsXs, G, B, Ctx, N1, N, O1, O
517instX, G, B, Ctx, N0, N, O0, O ⟶
form_ofX, Code, Fields
groupCode, G
→
true
else
nfb_error'~q is not a ~w', X, G
phrasefieldsFields, Ctx, B, Defs, [], Uses, [], Polls, [], Ws
Ctx = fctxTemps, _, _, _
rebindsDefs, Temps, N0, N, Rebinds
ordered_usesG, Uses, N0
→
O = O0
else
O = false
lengthWs, L0
L is L0 + 1
Header is Code \/ L << 16
memberR, Rebinds
R > 0
→
lengthRebinds, RL0
RL is RL0 + 1
RH is RC \/ RL << 16
RH
seqRebinds
else
[]
Header
seqWs
532must_lengthL ←
L < 1 << 16
!
533must_lengthL ←
nfb_error'an instruction of ~w words is longer than 65535', L
rebinds+Defs, +Temps, +N0, -N, -Words

each definition's rebind word, 0 for a first definition (it takes the next id, N0) or Id+1.

537rebinds[], _, N, N, []
538rebindsD|Ds, Temps, N0, N, W|Ws ←
get_assocD, Temps, Id
Id =:= N0
→
W = 0
N1 is N0 + 1
else
W is Id + 1
N1 = N0
rebindsDs, Temps, N1, N, Ws
545ordered_usesphi, _, _ ←
!
546ordered_uses_, Uses, N0 ←
forallmemberU, Uses, U < N0
547ordered_targetsPolls, B ←
forallmemberI−P, Polls,
I > B
or
P ≡ 1
fields+Fields, +Ctx, +B, Defs, Uses, Polls//

the words of Fields.

550fields[], _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
[]
551fieldsF|Fs, Ctx, B, Ds0, Ds, Us0, Us, Ps0, Ps ⟶
fieldF, Ctx, B, Ds0, Ds1, Us0, Us1, Ps0, Ps1
fieldsFs, Ctx, B, Ds1, Ds, Us1, Us, Ps1, Ps
555fielddefD, _, _, D|Ds, Ds, Us, Us, Ps, Ps ⟶
!
556fieldlocal_def_, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
!
557fieldclassK, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
!
codeclass, K
558fieldenumE, X, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
!
codeE, X
559fieldu32N, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
560fieldi64N, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
!
561fieldopndV, Ctx, _, Ds, Ds, Us0, Us, Ps, Ps ⟶
!
operandV, Ctx, Us0, Us
562fieldlabelL, fctx_, Ls, _, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
!
label_indexL, Ls, I
I
563fieldtargetT, fctx_, Ls, _, _, _, Ds, Ds, Us, Us, I−P|Ps, Ps ⟶
!
T = pollL
→
P = 1
else
L = T
P = 0
label_indexL, Ls, I
W is I << 1 \/ P
W
565fieldlocalX, fctx_, _, Xs, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
!
get_assocX, Xs, I
→
true
else
nfb_error'no local named ~q', X
I
567fieldstrA, fctx_, _, _, tables_, _, _, _, Strs, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
!
get_assocA, Strs, I
I
569fieldresultR, _, _, Ds0, Ds, Us, Us, Ps, Ps ⟶
!
phraseresult_defsR, Ds0, Ds
570fieldaltX, Alts, Ctx, B, Ds0, Ds, Us0, Us, Ps0, Ps ⟶
!
memberTag−X1−Fs, Alts
copy_termX1−Fs, X−Fs1
→
true
else
nfb_error'no alternative for ~q', X
Tag
fieldsFs1, Ctx, B, Ds0, Ds, Us0, Us, Ps0, Ps
573fieldcountXs, X, Fs, Ctx, B, Ds0, Ds, Us0, Us, Ps0, Ps ⟶
!
lengthXs, N
N
elemsXs, X, Fs, Ctx, B, Ds0, Ds, Us0, Us, Ps0, Ps
575fieldrestXs, X, Fs, Ctx, B, Ds0, Ds, Us0, Us, Ps0, Ps ⟶
!
is_listXs
→
true
else
nfb_error'not a list: ~q', Xs
elemsXs, X, Fs, Ctx, B, Ds0, Ds, Us0, Us, Ps0, Ps
579elems[], _, _, _, _, Ds, Ds, Us, Us, Ps, Ps ⟶
[]
580elemsE|Es, X, Fs, Ctx, B, Ds0, Ds, Us0, Us, Ps0, Ps ⟶
copy_termX−Fs, X1−Fs1
X1 = E
→
true
else
nfb_error'no encoding for the element ~q', E
fieldsFs1, Ctx, B, Ds0, Ds1, Us0, Us1, Ps0, Ps1
elemsEs, X, Fs, Ctx, B, Ds1, Ds, Us1, Us, Ps1, Ps
585label_indexL, Ls, I ←
get_assocL, Ls, I
!
586label_indexL, _, _ ←
nfb_error'no block labelled ~q', L
588result_wordvoid ⟶
!
0
589result_wordresulttmp_, K ⟶
!
codeclass, K
590result_wordtupleresulttmp_, K1, resulttmp_, K2 ⟶
!
nfb_codeclass, K1, C1
nfb_codeclass, K2, C2
W is 0x100 + 16 × C1 + C2
W
592result_wordR ⟶
nfb_error'no encoding for the call result ~q', R
594codeE, X ⟶
nfb_codeE, X, C
!
C
595codeE, X ⟶
nfb_error'no ~w code for ~q', E, X
597operandtmpN, fctxTemps, _, _, _, Id|Us, Us ⟶
!
get_assocN, Temps, Id
→
true
else
nfb_error'tmp(~q) is read but never defined', N
W is Id << 2
W
600operandconstN, fctx_, _, _, T, Us, Us ⟶
601operandglobalS, fctx_, _, _, tables_, _, _, SymIds, _, _, Us, Us ⟶
!
get_assocS, SymIds, I
W is I << 2 \/ 3
W
603operandV, _, _, _ ⟶
nfb_error'no encoding for the value ~q', V
605const_wordN, _ ⟶
!
W is N mod 1 << 30 << 2 \/ 1
W
606const_wordN, tables_, _, _, _, _, Cs ⟶
integerN
get_assocN, Cs, I
!
W is I << 2 \/ 2
W
607const_wordN, _ ⟶
nfb_error'no encoding for the constant ~q', N

Words

611must_u32N ←
integerN
N ≥ 0
N < 1 << 32
!
612must_u32N ←
nfb_error'~q does not fit in a word', N
614i64N ⟶
integerN
N ≥ −1 << 63
N < 1 << 63
→
true
else
nfb_error'~q does not fit in 64 bits', N
U is N mod 1 << 64
Lo is U /\ 0xFFFFFFFF
Hi is U >> 32
Lo, Hi
wideN//

N, from -2^95 to 2^95-1, as three words, low first.

619wideN ⟶
integerN
N ≥ −1 << 95
N < 1 << 95
→
true
else
nfb_error'~q does not fit in 96 bits', N
U is N mod 1 << 96
W0 is U /\ 0xFFFFFFFF
W1 is U >> 32 /\ 0xFFFFFFFF
W2 is U >> 64
W0, W1, W2
bytes_words+Bs//

the length of Bs, then Bs four to a word, low byte first, the last word padded with zero bytes.

626bytes_wordsBs ⟶
lengthBs, N
N
627packed[] ⟶
!
628packedBs ⟶
take4Bs, B0, B1, B2, B3, Rest
W is B0 \/ B1 << 8 \/ B2 << 16 \/ B3 << 24
W
packedRest
631take4B0, B1, B2, B3|R, B0, B1, B2, B3, R ←
!
632take4Bs, B0, B1, B2, B3, [] ←
appendBs, Pad, B0, B1, B2, B3
maplist=0, Pad
atom_bytes+A, -Bs

the UTF-8 bytes of the atom A.

635atom_bytesA, Bs ←
atom_codesA, Cs
phraseutf8Cs, Bs
636utf8[] ⟶
[]
637utf8C|Cs ⟶
638utf8_codeC ⟶
C < 0x80
!
C
639utf8_codeC ⟶
C < 0x800
!
B0 is 0xC0 \/ C >> 6
B1 is 0x80 \/ C /\ 0x3F
B0, B1
640utf8_codeC ⟶
C < 0x10000
!
B0 is 0xE0 \/ C >> 12
B1 is 0x80 \/ C >> 6 /\ 0x3F
B2 is 0x80 \/ C /\ 0x3F
B0, B1, B2
642utf8_codeC ⟶
B0 is 0xF0 \/ C >> 18
B1 is 0x80 \/ C >> 12 /\ 0x3F
B2 is 0x80 \/ C >> 6 /\ 0x3F
B3 is 0x80 \/ C /\ 0x3F
B0, B1, B2, B3
646nfb_errorFmt, Args ←
formatatomMsg, Fmt, Args
atom_concat'nfb: ', Msg, Msg1
thrownanofil_errorMsg1

Side sections: terms

A side section's terms are written with their own string pool: the atoms and functors they use, sorted by bytes. A term is a tag word and its parts: 0 an integer (wide/1), 1 an atom, 2 a compound (its functor, its arity, its arguments), 3 a proper list (its length, its elements).

658side_terms_wordsTerms, Body ←
findallA,
memberT, Terms
,
As0
sortAs0, As1
sort_by_bytesAs1, Pool
numberedPool, 0, Ps
list_to_assocPs, Ids
phrasestrings_wordsPool, PoolWs0
Pool ≡ []
→
PoolWs = 0
else
PoolWs = PoolWs0
Body = Ids−PoolWs
666term_atomT, A ←
is_listT
!
memberX, T
667term_atomT, T ←
atomT
!
668term_atomT, A ←
compoundT
T =.. F|As
A = F
or
memberX, As
670side_termT, Ids ⟶
is_listT
!
lengthT, N
3, N
671side_termT, Ids ⟶
atomT
!
get_assocT, Ids, I
1, I
672side_termT, _ ⟶
integerT
!
0
673side_termT, Ids ⟶
compoundT
compound_name_arityT, _, N
N > 0
!
T =.. F|As
get_assocF, Ids, I
2, I, N
side_termsAs, Ids
675side_termT, _ ⟶
nfb_error'a side section cannot hold ~q', T
676side_terms[], _ ⟶
[]
677side_termsT|Ts, Ids ⟶
side_termT, Ids
side_termsTs, Ids
names_words+Recs, -Ws

NAMES: the pool, then per function its temporaries', labels' and locals' names, each list in id order.

681names_wordsRecs, Ws ←
findallN,
membernamesTs, Ls, Xs, Recs
memberN, Ts
or
memberN, Ls
or
memberN, Xs
,
All
side_terms_wordsAll, Ids−PoolWs
phrase
seqPoolWs
names_recsRecs, Ids
,
Ws
685names_recs[], _ ⟶
[]
686names_recsnamesTs, Ls, Xs|Rs, Ids ⟶
name_listTs, Ids
name_listLs, Ids
name_listXs, Ids
names_recsRs, Ids
688name_listNs, Ids ⟶
lengthNs, N
N
side_listNs, Ids
689side_list[], _ ⟶
[]
690side_listT|Ts, Ids ⟶
side_termT, Ids
side_listTs, Ids
context_words+Contexts, -Ws

CONTEXT: the pool, the count, then each context item's position among the other items and its term.

694context_wordsContexts, Ws ←
findallC, member_−C, Contexts, Cs
side_terms_wordsCs, Ids−PoolWs
lengthContexts, N
phrase
seqPoolWs
N
context_listContexts, Ids
,
Ws
699context_list[], _ ⟶
[]
700context_listP−C|Cs, Ids ⟶
P
side_termC, Ids

Reading

read_words+Ws, -M

M is the module the NFB Ws encode; Ws must be exactly its encoding, with the side sections Ws has.

706read_wordsWs, M ←
Ws = Magic, Version, Flags, NSecs|SecWs
magicMagic
versionVersion
Flags /\ \7 =:= 0
split_sectionsSecWs, Secs
lengthSecs, NSecs
forallmemberId−_, Secs,
Id ≥ 0x200
or
memberchkId, 1, 2, 3, 4, 5, 0x100, 0x101
sec1, Secs, 0, StrWs
sec2, Secs, 0, ConstWs
sec3, Secs, 0, SymWs
sec4, Secs, [], DataWs
sec5, Secs, [], FuncWs
phraseread_stringsStrs, StrWs
phraseread_constantsConsts, ConstWs
phraseread_symbolsSyms0, SymWs
StrT =.. s|Strs
ConstT =.. c|Consts
maplistsymbol_nameStrT, Syms0, Syms
SymT =.. y|Syms
memberchk0x100−NamesWs, Secs
→
phraseread_namesNames, NamesWs
Sides0 = names
else
Names = none
Sides0 = []
memberchk0x101−CtxWs, Secs
→
phraseread_contextsContexts, CtxWs
Sides = context|Sides0
else
Contexts = []
Sides = Sides0
R = rStrT, ConstT, SymT
phraseread_dataSyms, R, Datas, DataWs
phraseread_funcsSyms, R, Names, Funcs, FuncWs
build_itemsSyms, SymT, Datas, Funcs, Items
insert_contextsContexts, 0, Items, All
M = moduleAll
catchmodule_nfbM, Sides, Ws1, nanofil_error_, fail
sections_below0x200, Ws, Ws2
Ws1 ≡ Ws2
737section_ids_increase[], _
738section_ids_increaseId−_|Ss, Prev ←
Id > Prev
sec+Id, +Secs, +Empty, -Ws

the payload of section Id, or Empty, the payload that means none, when it is absent.

742secId, Secs, _, Ws ←
memberchkId−Ws, Secs
!
743sec_, _, Ws, Ws
745read_stringsStrs ⟶
N
read_nN, read_string, Strs
746read_stringA ⟶
phraseutf8_decodeCs, Bs
atom_codesA, Cs
747read_bytesBs ⟶
N
NW is N + 3//4
read_nNW, word_, Ws
unpackWs, Bs0
lengthBs, N
appendBs, _, Bs0
748word_W ⟶
W
749unpack[], []
750unpackW|Ws, B0, B1, B2, B3|Bs ←
B0 is W /\ 0xFF
B1 is W >> 8 /\ 0xFF
B2 is W >> 16 /\ 0xFF
B3 is W >> 24
unpackWs, Bs
754utf8_decode[] ⟶
[]
755utf8_decode_ ⟶
B
B ≥ 0xF8
!
fail
756utf8_decodeC|Cs ⟶
B0
B0 < 0x80
!
C = B0
757utf8_decodeC|Cs ⟶
B0, B1
B0 ≥ 0xC0
B0 < 0xE0
!
C is B0 /\ 0x1F << 6 \/ B1 /\ 0x3F
759utf8_decodeC|Cs ⟶
B0, B1, B2
B0 ≥ 0xE0
B0 < 0xF0
!
C is B0 /\ 0x0F << 12 \/ B1 /\ 0x3F << 6 \/ B2 /\ 0x3F
¬
C ≥ 0xD800
C ≤ 0xDFFF
762utf8_decodeC|Cs ⟶
B0, B1, B2, B3
B0 ≥ 0xF0
!
C is B0 /\ 0x07 << 18 \/ B1 /\ 0x3F << 12 \/ B2 /\ 0x3F << 6 \/ B3 /\ 0x3F
C ≤ 0x10FFFF
766read_n0, _, [] ⟶
!
767read_nN, G, X|Xs ⟶
callG, X
N1 is N−1
read_nN1, G, Xs
769read_constantsCs ⟶
N
read_nN, read_wide, Cs
770read_wideN ⟶
W0, W1, W2
U is W0 \/ W1 << 32 \/ W2 << 64
U ≥ 1 << 95
→
N is U−1 << 96
else
N = U
771read_i64N ⟶
Lo, Hi
U is Lo \/ Hi << 32
U ≥ 1 << 63
→
N is U−1 << 64
else
N = U
773read_symbolsSs ⟶
N
read_nN, read_symbol, Ss
774read_symbolsymSid, K, L, Extra ⟶
Sid, W, Extra
K is W /\ 0xFF
L is W >> 8
table_arg+I, +Table, ?X

X is the Ith element of a table the reader built with =.., which has no arguments when it is empty.

778table_argI, T, X ←
compoundT
argI, T, X
780symbol_nameStrT, symSid, K, L, E, symName, K, L, E ←
I is Sid + 1
table_argI, StrT, Name
read_data+Syms, +R, -Datas//

data(Name, Linkage, Align, Items) of each kind-1 symbol, in order.

784read_data[], _, [] ⟶
[]
785read_datasymN, 1, L, E|Ss, R, dataN, Lk, Al, Its|Ds ⟶
!
nfb_codedata_linkage, Lk0, L
Lk0 = initW, priority
→
Lk = initW, E
else
Lk = Lk0
Al, NI
read_nNI, read_data_itemR, Its
read_dataSs, R, Ds
788read_data_|Ss, R, Ds ⟶
read_dataSs, R, Ds
790read_data_item_, itemb, strCs ⟶
1
!
maplistbyte_char, Bs, Cs
791read_data_itemR, itemW, constN ⟶
0
!
CW
nfb_codewidth, W, CW
792read_data_itemR, itemW, symS, Off ⟶
2
!
CW, Sid
nfb_codewidth, W, CW
sym_nameR, Sid, S
793read_data_item_, zeroN ⟶
795byte_charB, C ←
char_codeC, B
797read_constr_, ConstT, _, N ⟶
W
const_valueW, ConstT, N
798const_valueW, _, N ←
W /\ 3 =:= 1
!
P is W >> 2
P ≥ 1 << 29
→
N is P−1 << 30
else
N = P
799const_valueW, ConstT, N ←
W /\ 3 =:= 2
I is W >> 2 + 1
table_argI, ConstT, N
801sym_namer_, _, SymT, Sid, Name ←
I is Sid + 1
table_argI, SymT, symName, _, _, _
build_items+Syms, +SymT, +Datas, +Funcs, -Items

the items in symbol order: each defined symbol's function, data or alias.

805build_items[], _, [], [], []
806build_itemssym_, 0, _, _|Ss, SymT, Ds, F|Fs, F|Is ←
!
build_itemsSs, SymT, Ds, Fs, Is
807build_itemssym_, 1, _, _|Ss, SymT, D|Ds, Fs, D|Is ←
!
build_itemsSs, SymT, Ds, Fs, Is
808build_itemssymN, 2, L, Tg|Ss, SymT, Ds, Fs, aliasN, Lk, TgN|Is ←
!
nfb_codealias_linkage, Lk, L
I is Tg + 1
table_argI, SymT, symTgN, _, _, _
build_itemsSs, SymT, Ds, Fs, Is
811build_itemssym_, 3, _, _|Ss, SymT, Ds, Fs, Is ←
build_itemsSs, SymT, Ds, Fs, Is
813insert_contexts[], _, Is, Is ←
!
814insert_contextsP−C|Cs, I, Is, C|All ←
P =:= I
!
insert_contextsCs, I, Is, All
815insert_contextsCs, I, It|Is, It|All ←
I1 is I + 1
insert_contextsCs, I1, Is, All

Side sections.

818read_poolPoolT ⟶
PoolT =.. p|Pool
819read_side_termP, T ⟶
Tag
820read_side_term0, _, N ⟶
821read_side_term1, P, A ⟶
I
I1 is I + 1
table_argI1, P, A
822read_side_term2, P, T ⟶
I, N
I1 is I + 1
table_argI1, P, F
read_nN, read_side_termP, As
T =.. F|As
823read_side_term3, P, T ⟶
N
read_nN, read_side_termP, T
825read_namesnamesRecs ⟶
826read_name_recs_, [] ⟶
827read_name_recsP, namesTs, Ls, Xs|Rs ⟶
NT
read_nNT, read_side_termP, Ts
NL
read_nNL, read_side_termP, Ls
NX
read_nNX, read_side_termP, Xs
831read_contextsCs ⟶
N
read_nN, read_contextP, Cs
832read_contextP, Pos−C ⟶
read_funcs+Syms, +R, +Names, -Funcs//

the function of each kind-0 symbol, named from Names or by ids.

836read_funcsSyms, R, Names, Funcs ⟶
Names = namesRecs
→
true
else
Recs = none
read_funcs_Syms, R, Recs, Funcs
839read_funcs_[], _, Recs, [] ⟶
Recs ≡ none
or
Recs ≡ []
!
840read_funcs_symN, 0, L, _|Ss, R, Recs0, F|Fs ⟶
!
Recs0 ≡ none
→
Rec = none
Recs = none
else
Recs0 = Rec|Recs
nfb_codefunc_linkage, Lk, L
Len
takeLen, BodyWs
phraseread_bodyR, Rec, N, Lk, F, BodyWs
read_funcs_Ss, R, Recs, Fs
846read_funcs__|Ss, R, Recs, Fs ⟶
read_funcs_Ss, R, Recs, Fs
848read_bodyR, Rec, Name, Lk, funcName, Lk, Ret, Ps, Bs ⟶
RW
read_retRW, Ret
NP
read_nNP, word_, PKs
NB, NT, NL
Each block, definition and local takes a word of the stream at
least, so a count beyond its length is refused before it sizes a
table.
lengthRest, Left
NB ≤ Left
NT−NP ≤ Left
NL ≤ Left
name_tablesRec, NT, NB, NL, TN, LN, XN
numlist_0, NP, PIds
maplistread_paramTN, PKs, PIds, Ps
Ctx = dctxTN, LN, XN, R
read_blocks0, NB, Ctx, NP, NT, 0, NL, Bs
863read_paramTN, C, Id, paramK, tmpD ←
nfb_codeclass, K, C
memberchkK, w, l, p, s, d
I is Id + 1
table_argI, TN, D
866read_ret0, void ←
!
867read_ret15, data ←
!
868read_retW, tupleK1, K2 ←
W ≥ 0x100
!
C1 is W−0x100 >> 4
C2 is W /\ 15
nfb_codeclass, K1, C1
nfb_codeclass, K2, C2
869read_retW, K ←
nfb_codeclass, K, W
871numlist_N, N, [] ←
!
872numlist_I, N, I|Is ←
I1 is I + 1
numlist_I1, N, Is
name_tables+Rec, +NT, +NB, +NL, -TN, -LN, -XN

terms whose arguments are the names by id: from NAMES, or the ids themselves.

876name_tablesnone, NT, NB, NL, TN, LN, XN ←
!
numlist_0, NT, Ts
numlist_0, NB, Ls
numlist_0, NL, Xs
TN =.. t|Ts
LN =.. l|Ls
XN =.. x|Xs
879name_tablesnamesTs, Ls, Xs, NT, NB, NL, TN, LN, XN ←
lengthTs, NT
lengthLs, NB
lengthXs, NL
TN =.. t|Ts
LN =.. l|Ls
XN =.. x|Xs
read_blocks+I, +NB, +Ctx, +N0, +NT, +X0, +NL, -Bs//

the blocks from index I; N0 temporaries and X0 locals defined before them.

885read_blocksNB, NB, _, NT, NT, NL, NL, [] ⟶
!
886read_blocksI, NB, Ctx, N0, NT, X0, NL, blockL, Phis, Insts, J|Bs ⟶
I < NB
I1 is I + 1
Ctx = dctx_, LN, _, _
table_argI1, LN, L
read_groupphi, Ctx, N0, N1, X0, X1, Phis
I =:= 0
→
Phis ≡ []
else
true
read_groupplain, Ctx, N1, N2, X1, X2, Insts
read_instCtx, N2, N3, X2, X3, jump, J
read_blocksI1, NB, Ctx, N3, NT, X3, NL, Bs
894read_groupG, Ctx, N0, N, X0, X, I|Is ⟶
!
read_instCtx, N0, N1, X0, X1, G, I
read_groupG, Ctx, N1, N, X1, X, Is
896read_group_, _, N, N, X, X, [] ⟶
[]
898lookaheadWs, Ws, Ws

at_end//: no words are left.

901at_end[], []
next_group+Ws, ?G

the next instruction of Ws, after any rebind, is of group G.

905next_groupH|Ws, G ←
Op is H /\ 0xFFFF
→
L is H >> 16−1
L ≥ 1
lengthSkip, L
appendSkip, H2|_, Ws
Op2 is H2 /\ 0xFFFF
groupOp2, G
else
groupOp, G
913take0, [] ⟶
!
914takeN, X|Xs ⟶
X
N1 is N−1
takeN1, Xs
916read_instCtx, N0, N, X0, X, G, Inst ⟶
H
H /\ 0xFFFF =:= 0x01
→
L is H >> 16
RL is L−1
RL ≥ 1
takeRL, Rebinds
else
Rebinds = none
H1
Code is H1 /\ 0xFFFF
L1 is H1 >> 16
L1 ≥ 1
groupCode, G
nfb_formCode, Inst, Fields
N1 is L1−1
takeN1, Ws
phraseread_fieldsFields, Ctx, X0, X, Slots, [], Ws
bind_defsSlots, Rebinds, Ctx, N0, N
bind_defs+Slots, +Rebinds, +Ctx, +N0, -N

each definition's name: the next id's, or the rebound id's.

927bind_defsSlots, none, Ctx, N0, N ←
!
lengthSlots, K
lengthWs, K
maplist=0, Ws
bind_defsSlots, Ws, Ctx, N0, N
929bind_defs[], [], _, N, N
930bind_defsD|Ds, W|Ws, Ctx, N0, N ←
Ctx = dctxTN, _, _, _
W =:= 0
→
Id = N0
N1 is N0 + 1
else
Id is W−1
Id < N0
N1 = N0
I is Id + 1
table_argI, TN, D
bind_defsDs, Ws, Ctx, N1, N
936read_fields[], _, X, X, Ds, Ds ⟶
[]
937read_fieldsF|Fs, Ctx, X0, X, Ds0, Ds ⟶
read_fieldF, Ctx, X0, X1, Ds0, Ds1
read_fieldsFs, Ctx, X1, X, Ds1, Ds
940read_fielddefD, _, X, X, D|Ds, Ds ⟶
!
941read_fieldlocal_defN, dctx_, _, XN, _, X0, X, Ds, Ds ⟶
!
X is X0 + 1
table_argX, XN, N
943read_fieldclassK, _, X, X, Ds, Ds ⟶
!
C
nfb_codeclass, K, C
944read_fieldenumE, V, _, X, X, Ds, Ds ⟶
!
C
nfb_codeE, V, C
945read_fieldu32N, _, X, X, Ds, Ds ⟶
!
N
946read_fieldi64N, _, X, X, Ds, Ds ⟶
947read_fieldopndV, dctxTN, _, _, R, X, X, Ds, Ds ⟶
!
W
operand_valueW, TN, R, V
948read_fieldlabelL, dctx_, LN, _, _, X, X, Ds, Ds ⟶
!
I
I1 is I + 1
table_argI1, LN, L
949read_fieldtargetT, dctx_, LN, _, _, X, X, Ds, Ds ⟶
!
W
I is W >> 1 + 1
table_argI, LN, L
W /\ 1 =:= 1
→
T = pollL
else
T = L
951read_fieldlocalN, dctx_, _, XN, _, X, X, Ds, Ds ⟶
!
I
I1 is I + 1
table_argI1, XN, N
952read_fieldstrA, dctx_, _, _, rStrT, _, _, X, X, Ds, Ds ⟶
!
I
I1 is I + 1
table_argI1, StrT, A
953read_fieldresultRes, _, X, X, Ds0, Ds ⟶
!
W
read_resultW, Res, Ds0, Ds
954read_fieldaltV, Alts, Ctx, X0, X, Ds0, Ds ⟶
!
Tag
memberTag−V1−Fs, Alts
!
copy_termV1−Fs, V−Fs1
read_fieldsFs1, Ctx, X0, X, Ds0, Ds
957read_fieldcountXs, E, Fs, Ctx, X0, X, Ds0, Ds ⟶
!
N
read_elemsN, Xs, E, Fs, Ctx, X0, X, Ds0, Ds
958read_fieldrestXs, E, Fs, Ctx, X0, X, Ds0, Ds ⟶
!
read_restXs, E, Fs, Ctx, X0, X, Ds0, Ds
960read_elems0, [], _, _, _, X, X, Ds, Ds ⟶
!
961read_elemsN, V|Vs, E, Fs, Ctx, X0, X, Ds0, Ds ⟶
copy_termE−Fs, V−Fs1
read_fieldsFs1, Ctx, X0, X1, Ds0, Ds1
N1 is N−1
read_elemsN1, Vs, E, Fs, Ctx, X1, X, Ds1, Ds
965read_rest[], _, _, _, X, X, Ds, Ds ⟶
966read_restV|Vs, E, Fs, Ctx, X0, X, Ds0, Ds ⟶
copy_termE−Fs, V−Fs1
read_fieldsFs1, Ctx, X0, X1, Ds0, Ds1
read_restVs, E, Fs, Ctx, X1, X, Ds1, Ds
970read_result0, void, Ds, Ds ←
!
971read_resultW, tupleresulttmpD1, K1, resulttmpD2, K2, D1, D2|Ds, Ds ←
W ≥ 0x100
!
C1 is W−0x100 >> 4
C2 is W /\ 15
nfb_codeclass, K1, C1
nfb_codeclass, K2, C2
973read_resultW, resulttmpD, K, D|Ds, Ds ←
nfb_codeclass, K, W
975operand_valueW, TN, R, V ←
Tag is W /\ 3
P is W >> 2
Tag =:= 0
→
I is P + 1
table_argI, TN, N
V = tmpN
Tag =:= 3
→
sym_nameR, P, S
V = globalS
else
R = r_, ConstT, _
const_valueW, ConstT, N
V = constN

Files

write_nfb_file+File, +Wordsdet

Write Words to File, each as four bytes, low byte first.

987write_nfb_fileFile, Ws ←
setup_call_cleanupopenFile, write, S, typebinary, maplistput_wordS, Ws, closeS
991put_wordS, W ←
B0 is W /\ 0xFF
B1 is W >> 8 /\ 0xFF
B2 is W >> 16 /\ 0xFF
B3 is W >> 24
put_byteS, B0
put_byteS, B1
put_byteS, B2
put_byteS, B3
read_nfb_file+File, -Wordsdet

Words are the little-endian words of File. Throws nanofil_error(Msg) when its length is not a multiple of four.

999read_nfb_fileFile, Ws ←
setup_call_cleanupopenFile, read, S, typebinary, read_file_wordsS, Ws, closeS
1003read_file_wordsS, Ws ←
get_byteS, B0
B0 =:= -1
→
Ws = []
else
get_byteS, B1
get_byteS, B2
get_byteS, B3
B3 =:= -1
→
nfb_error'the file is not a whole number of words', []
else
true
W is B0 \/ B1 << 8 \/ B2 << 16 \/ B3 << 24
Ws = W|Ws1