BQN-based build system
This commit is contained in:
parent
efcc6a28be
commit
d38316e670
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,6 +8,7 @@ libcbqn.so
|
||||
|
||||
# build system things
|
||||
/build/obj/
|
||||
/build/obj2/
|
||||
/build/singeliLocal
|
||||
/build/replxxLocal
|
||||
/build/bytecodeLocal
|
||||
|
||||
3
build/build
Executable file
3
build/build
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
DIR="$(dirname $0)"
|
||||
"$DIR/obj2/for_build" "$DIR/src/build.bqn" "$@"
|
||||
@ -13,7 +13,7 @@ depfile ← (At buildDir) •file.At filename∾".d"
|
||||
prefix ← "si_"∾ (∧`'.'⊸≠)⊸/ •file.Name srcfile
|
||||
|
||||
# invoke singeli, which creates the result file
|
||||
(⟨"-d" ⋄ tmpfile ⋄ "-o" ⋄ resfile ⋄ "-n" ⋄ prefix ⋄ srcfile⟩) •Import siDir •file.At "singeli"
|
||||
(⟨"-l", "gen=src/singeli/gen", "-d" ⋄ tmpfile ⋄ "-o" ⋄ resfile ⋄ "-n" ⋄ prefix ⋄ srcfile⟩) •Import siDir •file.At "singeli"
|
||||
|
||||
# output dependency file
|
||||
deps ← siDir⊸•file.At¨ •file.Lines tmpfile
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 2fefe457b47005f1aff2e67f73bbef7eb9173833
|
||||
Subproject commit f60a3c73450b8d5ae18bdc76f090b20437cf7ab2
|
||||
545
build/src/build.bqn
Executable file
545
build/src/build.bqn
Executable file
@ -0,0 +1,545 @@
|
||||
#!build/obj2/for_build
|
||||
|
||||
# to emulate on makefile transition: NO_LDL → rm_lf=-ldl; no_fPIC → rm_f=-fPIC; something something PIE
|
||||
|
||||
⟨Spawn, WaitForOne⟩ ← ⟨⟩ •Import "fork.bqn"
|
||||
⟨Serialize, Deserialize⟩ ← •Import "serialize.bqn"
|
||||
|
||||
# modes:
|
||||
# 0: single string option
|
||||
# 1: toggle
|
||||
# 2: flag list
|
||||
opts ← ⟨
|
||||
⟨0, "j", "4"⟩ # number of parallel jobs
|
||||
⟨1, "verbose", 0⟩ # log more things
|
||||
⟨1, "rebuild", 0⟩ # forcibly rebuild everything
|
||||
# TODO clean
|
||||
|
||||
⟨0, "CC", @⟩ # the C compiler
|
||||
⟨0, "LD", @⟩ # linker of the final binary; default CC, or CXX if REPLXX=1
|
||||
⟨1, "color", 1⟩ # whether to enable colored diagnostics
|
||||
⟨0, "os", @⟩ # target OS (linux, bsd, macos); used for .so vs .dylib, and changing linker flags for bsd
|
||||
⟨0, "arch", @⟩ # target architecture (x86-64, aarch64, generic); used for Singeli target deciding
|
||||
|
||||
⟨0, "OUTPUT", ""⟩ # output location; default depends
|
||||
⟨2, "f", ⟨⟩⟩ # C flags for CBQN files
|
||||
⟨2, "CCFLAGS", ⟨⟩⟩ # flags for all C compiler & linker invocations
|
||||
⟨2, "lf", ⟨⟩⟩ # linker flags
|
||||
⟨2, "LDFLAGS", ⟨⟩⟩ # more linker flags (identical to lf)
|
||||
⟨2, "rm_f", ⟨⟩⟩ # forcibly remove C compiler flag(s)
|
||||
⟨2, "rm_lf", ⟨⟩⟩ # forcibly remove linker flag(s)
|
||||
|
||||
# also define the default OUTPUT value (default default being "BQN")
|
||||
⟨1, "shared", 0⟩ # build a shared library; OUTPUT = "libcbqn.[so|dylib]"
|
||||
⟨1, "wasi", 0⟩ # build with WASI; OUTPUT = "BQN.wasm"
|
||||
⟨1, "emcc", 0⟩ # build with emscripten; OUTPUT = ".", is used as a directory
|
||||
|
||||
⟨1, "FFI", @⟩ # enable FFI through libffi; default ≡ ¬wasi∨emcc
|
||||
⟨1, "pkgconfig", 1⟩ # attempt to use pkg-config to find libffi inclusion flags
|
||||
⟨1, "singeli", 0⟩ # enable Singeli
|
||||
⟨1, "REPLXX", 0⟩ # enable replxx
|
||||
# TODO options for forcing around the bytecode/singeli/replxx directories
|
||||
|
||||
# CBQN toggles
|
||||
⟨1, "rtverify", 0⟩
|
||||
⟨1, "heapverify", 0⟩
|
||||
|
||||
⟨1, "c", 0⟩ # disable some default flags
|
||||
⟨1, "O3", @⟩ # -O3; default ≡ ¬c
|
||||
⟨1, "g", @⟩ # -g; default ≡ debug
|
||||
⟨1, "native", 0⟩ # -march=native & use native arch as lower & upper bound for Singeli
|
||||
⟨1, "debug", 0⟩ # -DDEBUG & -g
|
||||
|
||||
⟨0, "CXX", "c++"⟩ # C++ compiler (for replxx)
|
||||
⟨2, "REPLXX_FLAGS", ⟨"-std=c++11", "-Os"⟩⟩ # default replxx C++ build flags
|
||||
⟩
|
||||
|
||||
Log ← •Out
|
||||
_verboseLog ← {𝔽_𝕣:⊢}
|
||||
onExitList ← ⟨⟩
|
||||
OnExit ← {𝕊: {𝕏@}¨ onExitList}
|
||||
_assert_ ← { 𝔾𝕩?𝕩; Log 𝕨𝔽𝕩 ⋄ OnExit@ ⋄ •Exit 1}
|
||||
|
||||
SepArgs ← {' ' ((¬-˜⊢×·+`»⊸>)∘≠⊔⊢) 𝕩}
|
||||
Lowercase ← {𝕩 - (-´"Aa")×(𝕩≥'A')∧𝕩≤'Z'}
|
||||
|
||||
getOpt ← {
|
||||
args ← ×∘≠¨⊸/ •args
|
||||
[ot, on0, od] ← ⍉>opts
|
||||
on ← Lowercase¨ on0
|
||||
ot1 ← 1=ot
|
||||
ot2 ← 2=ot
|
||||
|
||||
s1 ← ⊑∘⊐⟜'='¨ args # start of =
|
||||
hs ← s1<≠¨args # has value
|
||||
fl ← hs∧'+'=(0⌈s1-1)⊑¨args # is appended flag, i.e. "f+=a b c"
|
||||
s0 ← s1-fl # end of key
|
||||
ks ← s0↑¨args # keys
|
||||
ks Lowercase¨↩ # lowercase keys
|
||||
vs ← (1+s1)↓¨args # values
|
||||
{𝕊: "Unknown option -- "∾⊑(¬ks∊on)/ks}_assert_(∧´) ks∊on
|
||||
|
||||
ci ← on⊐ks # index in option specification
|
||||
{𝕊: ∾⟨"Error: Unexpected '+=' for '",ks⊑˜⊑/¬𝕩,"'"⟩}_assert_(∧´) (ci⊏ot2)∨¬fl
|
||||
|
||||
Gr ← {(≠ot)↑ci⊔𝕩}
|
||||
gvs ← Gr vs # values for each option
|
||||
{𝕊: ∾⟨"Error: Multiple values given for '",on⊑˜⊑/¬𝕩,"'"⟩}_assert_(∧´) ot2∨1≥≠¨gvs
|
||||
|
||||
{𝕊: ∾⟨"Error: Expected value to be provided for ",⊑𝕩/ks⟩}_assert_(¬∨´) (¬ci⊏ot1) ∧ ¬hs
|
||||
|
||||
# f='a b' f+='c d' → "a" "b" "c d"
|
||||
gvs ↩ (Gr fl) (∾{𝕨?⋈𝕩;×≠𝕩?SepArgs 𝕩;⋈⟨⟩}¨)¨⌾(ot2⊸/) gvs
|
||||
# map toggles to their actual values, error on invalid
|
||||
gvs ↩ on {𝕨{𝕊: ∾⟨"Error: Invalid value for '",𝕨,"'"⟩}_assert_⊢ ∧´𝕩∊""‿"0"‿"1" ⋄ ≠◶⊢‿(⋈"0"≢⊑) 𝕩}¨⌾(ot1⊸/) gvs
|
||||
|
||||
gvs ↩ ((¬ot2) ⋈∘⊢⍟⊣¨ od) {×≠𝕩?𝕩;𝕨}¨ gvs # map in defaults
|
||||
|
||||
gvs ↩ (¬ot2) ⋈⁼∘⊢⍟⊣¨ gvs # disclose options with only one expected result
|
||||
|
||||
# •Show [ks, fl, hs, ci, vs]
|
||||
# •Show {𝕩/˜×(≠1⊑⊢)˘𝕩} ⍉[on, gvs]
|
||||
{(⊑on⊐<Lowercase 𝕩)⊑gvs}
|
||||
}
|
||||
|
||||
SH ← {
|
||||
c‿o‿e ← •SH⎊{𝕊: 𝕩 {𝕊: ∾⟨"Error: Failed to spawn ",⊑𝕨⟩}_assert_⊢ 0} 𝕩
|
||||
Log⍟(×≠) e
|
||||
𝕩 {𝕊: ∾⟨"Error: ",⊑𝕨," exited with error code ",•Repr 𝕩⟩}_assert_(0=⊢) c
|
||||
o
|
||||
}
|
||||
|
||||
rootDir ← •file.Parent⍟2 •file.path
|
||||
AtRoot ← rootDir⊸•file.At
|
||||
|
||||
po ← { # parsed options
|
||||
⟨
|
||||
verbose, j, rebuildAll, output,
|
||||
os, arch, native,
|
||||
emcc, wasm, replxx, singeli,
|
||||
bytecodeDir, replxxDir, singeliDir,
|
||||
CBQNc, REPLXXc, Linker
|
||||
⟩⇐
|
||||
|
||||
custom ← GetOpt "c"
|
||||
DOpt ← {@⊸≡◶⟨⊢,𝕨⟩ GetOpt 𝕩}
|
||||
j ⇐ •BQN GetOpt "j"
|
||||
rebuildAll ⇐ GetOpt "rebuild"
|
||||
{𝕊: _verboseLog ↩ {Log𝕨𝔽𝕩⋄𝕩}}⍟⊢ verbose⇐GetOpt "verbose"
|
||||
|
||||
Max1 ← {𝕩 {𝕊: a‿b←2↑𝕩/𝕨 ⋄ ∾⟨"Error: '",a,"' and '",b,"' cannot both be enabled"⟩}_assert_(1≥+´) GetOpt¨ 𝕩}
|
||||
Max1 "REPLXX"‿"shared"‿"wasi"‿"emcc"
|
||||
|
||||
|
||||
shared ← GetOpt "shared"
|
||||
native ⇐ GetOpt "native"
|
||||
emcc ⇐ GetOpt "emcc"
|
||||
wasi ← GetOpt "wasi"
|
||||
wasm ⇐ wasi∨emcc
|
||||
|
||||
cc ← {emcc? "emcc"; "clang"} DOpt "CC"
|
||||
cxx ← GetOpt "CXX"
|
||||
ffi ← (¬wasm) DOpt "FFI"
|
||||
debug ← GetOpt "debug"
|
||||
singeli ⇐ GetOpt "singeli"
|
||||
replxx ⇐ GetOpt "REPLXX"
|
||||
|
||||
uname ← ⊢◶""‿{𝕊: Lowercase 1⊑•SH⎊1‿""‿"" "uname"‿"-sm"} ∧´ (@≡GetOpt)¨ "os"‿"arch"
|
||||
InUname ← {𝕊: ∨´ 𝕩⍷uname}
|
||||
|
||||
os ⇐ Lowercase {InUname"linux"? "linux"; InUname"darwin"? "macos"; InUname"bsd"? "bsd"; "linux"} DOpt "os"
|
||||
linux‿bsd‿macos ← os⊸≡¨ {𝕊: "Error: Unsupported OS; options:"∾1↓∾", "⊸∾¨𝕩}_assert_(⊑os<⊸∊⊢) "linux"‿"bsd"‿"macos"
|
||||
|
||||
arch ⇐ {'-'¨⌾(('_'=𝕩)⊸/)𝕩} Lowercase {InUname"x86_64"? "x86-64"; ∨´InUname¨"aarch64"‿"arm64"? "aarch64"; "generic"} DOpt "arch"
|
||||
{𝕊: "Error: Unsupported arch; options:"∾1↓∾", "⊸∾¨𝕩}_assert_(⊑arch <⊸∊⊢) "x86-64"‿"aarch64"‿"generic"
|
||||
|
||||
{𝕊: "Error: Cannot use Singeli on x86-64 without 'native'"}_assert_¬ (arch≡"x86-64")∧singeli∧¬native
|
||||
{𝕊: "Error: Cannot use Singeli on generic arch"}_assert_¬ singeli ∧ arch≡"generic"
|
||||
|
||||
output ⇐ GetOpt "OUTPUT"
|
||||
output ↩ •wdpath•file.At {𝕊:
|
||||
wasi? "BQN.wasm";
|
||||
emcc? ".";
|
||||
shared? "libcbqn." ∾ macos⊑"so"‿"dylib";
|
||||
"BQN"
|
||||
}⍟(""≡⊢) output
|
||||
|
||||
exportSymbols ← ffi∨shared
|
||||
|
||||
GetLibs ← { 𝕊:
|
||||
getLibs ↩ {
|
||||
¬ffi? ⟨⟨⟩,⟨⟩⟩;
|
||||
GetOpt "pkgconfig"? 0=⊑ •SH⎊1 "pkg-config"‿"--exists"‿"libffi"?
|
||||
{SepArgs ¯1↓SH⟨"pkg-config",𝕩,"libffi"⟩}¨ ⟨"--cflags", "--libs"⟩;
|
||||
⟨⟨⟩, ⟨"-lffi"⟩⟩
|
||||
}
|
||||
}
|
||||
|
||||
SubmoduleDir ← "build"⊸•file.At⍟(@≢⊢) {𝕨≡0?@; •file.Exists r←AtRoot "build"•file.At 𝕩∾"Local"? r; 𝕩∾"Submodule"}
|
||||
LogDir ← {𝕩≡@? 𝕨∾": not used"; 𝕨∾" directory: "∾AtRoot 𝕩}_verboseLog
|
||||
bytecodeDir ⇐ 1 SubmoduleDir "bytecode" ⋄ "Bytecode" LogDir bytecodeDir
|
||||
replxxDir ⇐ replxx SubmoduleDir "replxx" ⋄ "REPLXX" LogDir replxxDir
|
||||
singeliDir ⇐ singeli SubmoduleDir "singeli" ⋄ "Singeli" LogDir singeliDir
|
||||
{𝕊: "Output location: "∾𝕩}_verboseLog output
|
||||
|
||||
CBQNc ⇐ { 𝕊:
|
||||
isClang ← ∨´"clang"⍷SH cc‿"--version" # TODO exclude from hash?
|
||||
args ← ⟨
|
||||
cc,
|
||||
"-std=gnu11",
|
||||
"-Wall", "-Wno-unused-function",
|
||||
"-fms-extensions", "-ffp-contract=off", "-fno-math-errno", "-fvisibility=hidden",
|
||||
"-DBYTECODE_DIR="∾•file.Name bytecodeDir,
|
||||
"-DSINGELI="∾•Repr singeli,
|
||||
"-DFFI="∾•Repr 2×ffi
|
||||
⟩
|
||||
args∾↩ isClang⊑⟨
|
||||
⟨"-Wno-parentheses"⟩
|
||||
⟨"-Wno-microsoft-anon-tag", "-Wno-bitwise-instead-of-logical", "-Wno-unknown-warning-option"⟩
|
||||
⟩
|
||||
args∾↩ 0⊑GetLibs@
|
||||
|
||||
args∾↩ GetOpt "f"
|
||||
args∾↩ GetOpt "CCFLAGS"
|
||||
args∾↩ ( wasm) / ⟨"-DWASM"⟩
|
||||
args∾↩ ( wasi) / ⟨"-DWASI", "-DNO_MMAP", "-DCATCH_ERRORS=0", "-D_WASI_EMULATED_MMAN", "--target=wasm32-wasi"⟩
|
||||
args∾↩ ( emcc) / ⟨"-DEMCC", "-O3"⟩
|
||||
args∾↩ ( replxx) / ⟨"-DUSE_REPLXX", "-I"∾replxxDir∾"/include"⟩ # TODO maybe move to main.c only, and have it be in its own separate cache dir, so that adding replxx doesn't recompile everything?
|
||||
args∾↩ ( debug DOpt "g") / ⟨"-g"⟩
|
||||
args∾↩ ((¬custom) DOpt "O3") / ⟨"-O3"⟩
|
||||
args∾↩ ( native) / ⟨"-march=native"⟩
|
||||
args∾↩ ( debug) / ⟨"-DDEBUG"⟩
|
||||
args∾↩ ( GetOpt "color") / ⟨isClang⊑"-fdiagnostics-color=always"‿"-fcolor-diagnostics"⟩ # TODO exclude from hash?
|
||||
args∾↩ ( GetOpt "rtverify") / ⟨"-DRT_VERIFY", "-DEEQUAL_NEGZERO"⟩
|
||||
args∾↩ (GetOpt "heapverify") / ⟨"-DHEAP_VERIFY"⟩
|
||||
args∾↩ ( exportSymbols) / ⟨"-DCBQN_EXPORT"⟩
|
||||
args∾↩ ( shared) / ⟨"-DCBQN_SHARED", "-shared", "-fPIC"⟩
|
||||
args ↩ args (¬∘∊/⊣) GetOpt "rm_f"
|
||||
{"CBQN C compiler: "∾•Repr 𝕩} _verboseLog args
|
||||
cbqnc ↩ args
|
||||
}
|
||||
|
||||
REPLXXc ⇐ { 𝕊:
|
||||
args ← ⟨cxx, "-DREPLXX_STATIC=1", "-I"∾replxxDir∾"/include"⟩
|
||||
args∾↩ GetOpt "REPLXX_FLAGS"
|
||||
{"REPLXX C++ compiler: "∾•Repr 𝕩} _verboseLog args
|
||||
replxxc ↩ args
|
||||
}
|
||||
|
||||
Linker ⇐ { 𝕊:
|
||||
args ← ⟨{replxx? cxx; cc} DOpt "LD", "-lm"⟩
|
||||
args∾↩ 1⊑GetLibs@
|
||||
args∾↩ (¬bsd) / ⟨"-ldl"⟩
|
||||
args∾↩ GetOpt "lf"
|
||||
args∾↩ GetOpt "LDFLAGS"
|
||||
args∾↩ ( wasi) / ⟨"-lwasi-emulated-mman", "--target=wasm32-wasi", "-Wl,-z,stack-size=8388608", "-Wl,--initial-memory=67108864"⟩
|
||||
args∾↩ ( emcc) / ⟨"-s", "EXPORTED_FUNCTIONS=_main,_cbqn_runLine,_cbqn_evalSrc", "-s", "EXPORTED_RUNTIME_METHODS=ccall,cwrap", "-s", "ALLOW_MEMORY_GROWTH=1"⟩
|
||||
args∾↩ ( exportSymbols) / ⟨"-rdynamic"⟩
|
||||
args∾↩ ( linux ∧ arch≡"x86-64") / ⟨"-no-pie"⟩
|
||||
args ↩ args (¬∘∊/⊣) GetOpt "rm_lf"
|
||||
{"linker: "∾•Repr 𝕩} _verboseLog args
|
||||
linker ↩ args
|
||||
}
|
||||
|
||||
{𝕊: CBQNc@ ⋄ REPLXXc⍟replxx @ ⋄ Linker@}⍟⊢ verbose
|
||||
}
|
||||
|
||||
Hash ← {(32↑∾"0a"+↕¨10‿26)⊏˜{𝕨+2×𝕩}˝5‿⌊⥊32‿1•bit._cast∾(↕4)•Hash¨<𝕩}
|
||||
|
||||
MkDir ← {•file.Exists𝕩?@; •file.CreateDir𝕩}
|
||||
|
||||
allObjDir ← "build/obj2"
|
||||
MkDir AtRoot allObjDir
|
||||
|
||||
isFileTheSame ← {
|
||||
ks‿vs ← ⟨⟩‿⟨⟩
|
||||
{
|
||||
i ← ⊑ks⊐<𝕨
|
||||
i<≠ks? 𝕩 ≡ i⊑vs;
|
||||
ks∾↩ <𝕨
|
||||
vs∾↩ <t←•file.Modified 𝕨
|
||||
𝕩 ≡ t
|
||||
}
|
||||
}
|
||||
updateSubmodule ← {
|
||||
done ← ⟨⟩
|
||||
{
|
||||
𝕩≡@? @;
|
||||
"Local"≡¯5↑𝕩? @;
|
||||
⊑𝕩<⊸∊done? @;
|
||||
done∾↩ <𝕩
|
||||
SH ⟨"git", "submodule", "update", "--init", AtRoot 𝕩⟩
|
||||
}
|
||||
}
|
||||
|
||||
# gets/creates a directory of cacheable objects; key is the unique identifier of when it can be reused
|
||||
GetCache ← { 𝕊 basename‿desc‿key:
|
||||
hash ⇐ Hash key
|
||||
folder ⇐ allObjDir•file.At basename∾"-"∾hash
|
||||
MkDir AtRoot folder
|
||||
|
||||
File ⇐ folder⊸•file.At
|
||||
{𝕊: desc∾": "∾AtRoot𝕩} _verboseLog folder
|
||||
|
||||
dataPath ← AtRoot File "data"
|
||||
prevKs‿prevVs ← •file.Exists◶⟨⟨⟩‿⟨⟩, {Deserialize ⟨8‿'c',8⟩•bit._cast •FBytes 𝕩}⟩ dataPath
|
||||
|
||||
IsUpToDate ⇐ { 𝕊:
|
||||
i ← ⊑prevKs⊐<𝕩
|
||||
i<≠prevKs?
|
||||
{@:0; ∧´ AtRoot⊸IsFileTheSame´¨𝕩} i⊑prevVs;
|
||||
0
|
||||
}
|
||||
newKs‿newVs ← ⟨⟩‿⟨⟩
|
||||
Update ⇐ {key𝕊data: newKs∾↩ <key ⋄ newVs∾↩ <data} # data≡@ means failed to build
|
||||
onExitList∾↩ {{ 𝕊:
|
||||
jKs ← newKs∾prevKs
|
||||
jVs ← newVs∾prevVs
|
||||
dataPath •FBytes ⟨8,8‿'c'⟩•bit._cast Serialize (<∊jKs) /¨ jKs‿jVs
|
||||
}⍟{𝕊: 0≠≠newKs}}
|
||||
}
|
||||
|
||||
ruleKs‿ruleVs ← ⟨⟩‿⟨⟩
|
||||
AddRule ← { 𝕊 cache‿cacheKey‿dst‿GetCMD‿disp‿customDeps:
|
||||
ruleKs∾↩ <dst
|
||||
ruleVs∾↩ {
|
||||
cache ⇐ cache
|
||||
cacheKey ⇐ cacheKey
|
||||
disp ⇐ disp
|
||||
CMD ⇐ GetCMD
|
||||
ruleDeps ⇐ customDeps
|
||||
}
|
||||
}
|
||||
|
||||
# dependency resolution & thread management
|
||||
Run ← { 𝕊:
|
||||
ruleDeps ← {𝕩.ruleDeps}¨ ruleVs
|
||||
ruleSrcs0 ← ruleKs⊐∾ruleDeps
|
||||
! ∧´ ruleSrcs0<≠ruleKs
|
||||
ruleSrcs ← ((≠∾˜≠¨/↕∘≠)ruleDeps) ⊔ ruleSrcs0
|
||||
req ← ⟨⟩
|
||||
ruleN ← 0¨ ruleKs # number of children (i.e. how many have this in their ruleP list)
|
||||
ruleP ← ⟨⟩¨ ruleKs # parent rules (i.e. which ones require this)
|
||||
rebuildAll ← po.rebuildAll
|
||||
|
||||
Require ← {
|
||||
v ← 𝕩⊑ruleVs
|
||||
rebuild ← rebuildAll
|
||||
chi ← 𝕩⊑ruleSrcs
|
||||
chr ← Require¨ chi
|
||||
rebuild∨↩ ∨´ chr
|
||||
# rebuild∨↩ ¬•file.Exists AtRoot 𝕩⊑ruleKs # not really needed unless someone deletes a specific file without deleting the data file
|
||||
rebuild∨↩ ¬v.cache.IsUpToDate v.cacheKey
|
||||
{
|
||||
ruleN (+´chr)⊸+⌾(𝕩⊸⊑)↩
|
||||
ruleP ∾⟜𝕩¨⌾((chr/chi)⊸⊏)↩
|
||||
req∾↩ 𝕩
|
||||
}⍟rebuild 𝕩
|
||||
rebuild
|
||||
}
|
||||
anyRebuilt ← Require ⊑ruleKs⊐<𝕩
|
||||
|
||||
left ← (req⊏ruleN=0)/req
|
||||
|
||||
RequestJob ← { 𝕊:
|
||||
0=≠left? @;
|
||||
(left↓˜↩ ¯1) ⊢ ¯1⊑left
|
||||
}
|
||||
|
||||
FinishJob ← { i𝕊tb:
|
||||
v ← i⊑ruleVs
|
||||
Log⍟(×≠) 1⊑tb
|
||||
⊢◶⟨
|
||||
{ 𝕊:
|
||||
v.cacheKey v.cache.Update @
|
||||
}
|
||||
{ 𝕊:
|
||||
v.cacheKey v.cache.Update 3⊑tb
|
||||
ps ← i⊑ruleP
|
||||
ruleN -⟜1⌾(ps⊸⊏)↩
|
||||
left∾↩ (0=ps⊏ruleN)/ps
|
||||
}
|
||||
⟩ ⊑tb
|
||||
⊑tb
|
||||
}
|
||||
|
||||
threads ← Spawn∘(•file.At "runner.bqn")¨ ↕(≠req)⌊po.j
|
||||
work ← ⟨⟩
|
||||
free ← threads
|
||||
Ts ← {𝕩.t}¨
|
||||
|
||||
storedOut ← ⟨⟩
|
||||
Log ↩ {storedOut∾↩ <𝕩∾@+10}
|
||||
# Log ↩ {𝕊:1}
|
||||
currLive ← ⟨⟩
|
||||
e ← @+27
|
||||
UpdateLive ← {
|
||||
•term.OutRaw (∾(0⌈¯1+≠currLive)⥊<(e∾"[2K"∾e∾"[1F")) ∾ (•ToUTF8 ∾storedOut) ∾ 1↓∾((@+10)∾•ToUTF8)¨ 𝕩
|
||||
•term.Flush @
|
||||
currLive ↩ 𝕩
|
||||
storedOut ↩ ⟨⟩
|
||||
}
|
||||
FmtTime ← {{(""≡◶⊢‿"0" ¯1↓𝕩)∾'.'∾¯1↑𝕩} •Repr ⌊0.5+ 10×𝕩}
|
||||
onExitList∾↩ {{𝕊: UpdateLive ⟨⟩}}
|
||||
|
||||
tmap ← ⟨⟩ # threads in the order they're displayed on-screen (dynamically calculated so that if there's only ever only one job in parallel, there are no pointless empty lines)
|
||||
doneCount ← 0
|
||||
stopping ← 0
|
||||
Fail ← {stopping↩1 ⋄ Log 𝕩}
|
||||
t0 ← •MonoTime@
|
||||
DoneLine ← {𝕊: ∾⟨•Repr doneCount, "/", •Repr ≠req⟩}
|
||||
{ 𝕊:
|
||||
{𝕊:
|
||||
t ← ¯1⊑free ⋄ free↓˜↩ ¯1
|
||||
|
||||
i ← RequestJob@ ⋄ v←i⊑ruleVs
|
||||
t.Request v.CMD@
|
||||
work∾↩ {t⇐t, i⇐i, v⇐v, t0⇐•MonoTime@}
|
||||
|
||||
}•_while_{𝕊: ∧´0<≠¨ left‿free}⍟¬ stopping
|
||||
|
||||
t1 ← •MonoTime@
|
||||
tmap ↩ ⍷tmap∾Ts work
|
||||
UpdateLive (<DoneLine@)∾{
|
||||
𝕩≡≠work? "";
|
||||
o ← 𝕩⊑work
|
||||
∾⟨"[", FmtTime t1-o.t0, "] ", o.v.disp⟩
|
||||
}¨ (Ts work) ⊐tmap
|
||||
|
||||
dm ← 0.1 WaitForOne Ts work
|
||||
lm ← ¬dm
|
||||
{𝕊: Fail "Error: Fork died" ⋄ dm‿lm∧↩<dm≠¯1}⍟⊢ ∨´dm=¯1
|
||||
done ← dm/work
|
||||
work ↩ lm/work
|
||||
{𝕩.i FinishJob 𝕩.t.Take@? doneCount+↩1; Fail "Error: During '"∾𝕩.v.disp∾"'"}¨ done
|
||||
free∾↩ Ts done
|
||||
}•_while_{𝕊: (0<≠work) ∨ (¬stopping)∧0<≠left}@
|
||||
|
||||
Log ∾⟨DoneLine@, " in ", FmtTime t0-˜•MonoTime@, "s", stopping/"; failed to build"⟩
|
||||
|
||||
¬stopping
|
||||
}
|
||||
|
||||
|
||||
MakeCCInv ← { 𝕊 GetArgs‿Init‿cache‿id‿src‿customDeps: # src should be CBQN-base-dir-relative, so that cache doesn't store
|
||||
key ⇐ id
|
||||
dst ⇐ cache.File key∾".o"
|
||||
GetCMD ← { 𝕊:
|
||||
Init @
|
||||
dep ← AtRoot cache.File id∾".d"
|
||||
⟨"sh", rootDir, (GetArgs@)∾⟨"-MT", "o", "-MMD", "-MF", dep, "-o", AtRoot dst, "-c", src⟩, dep⟩
|
||||
}
|
||||
AddRule ⟨cache, key, dst, GetCMD, •file.Name src, customDeps⟩
|
||||
}
|
||||
|
||||
MakeSingeliInv ← { 𝕊 args‿Init‿cache‿id‿src‿customDeps: # src should be CBQN-base-dir-relative, so that cache doesn't store
|
||||
key ⇐ id
|
||||
dst ⇐ cache.File key∾".c"
|
||||
GetCMD ← { 𝕊:
|
||||
Init @
|
||||
dep ← AtRoot cache.File id∾".d"
|
||||
⟨"singeli", rootDir, AtRoot dst, AtRoot po.singeliDir, args, AtRoot src, dep⟩
|
||||
}
|
||||
AddRule ⟨cache, key, dst, GetCMD, •file.Name src, customDeps⟩
|
||||
}
|
||||
|
||||
MakeLinkerInv ← { 𝕊 GetArgs‿cache‿name‿srcs:
|
||||
dst ⇐ cache.File name
|
||||
GetCMD ← { 𝕊:
|
||||
args ← GetArgs@
|
||||
⟨"sh", rootDir, ⟨⊑args, "-o", dst⟩∾srcs∾1↓args, @⟩
|
||||
}
|
||||
AddRule ⟨cache, name, dst, GetCMD, "link", srcs⟩
|
||||
}
|
||||
|
||||
|
||||
|
||||
# actual CBQN/Singeli/REPLXX definitions
|
||||
cachedBin‿linkerCache ← {
|
||||
Shorten ← {r ← {𝕩↓˜¯1-⊑'.'⊐˜⌽𝕩}¨ •file.Name¨ 𝕩 ⋄ ! ∧´ ∊r ⋄ r}
|
||||
cbqnSrc ← ∾{⌽(⊑𝕩)⊸•file.At¨ 1↓𝕩}¨ ⌽⟨
|
||||
⟨"src/builtins/", "arithd.c", "arithm.c", "cmp.c", "sfns.c", "squeeze.c", "select.c", "slash.c", "group.c", "sort.c", "search.c", "selfsearch.c", "fold.c", "scan.c", "md1.c", "md2.c", "fns.c", "sysfn.c", "internal.c", "inverse.c"⟩
|
||||
⟨"src/core/", "tyarr.c", "harr.c", "fillarr.c", "stuff.c", "derv.c", "mm.c", "heap.c"⟩
|
||||
⟨"src/", "load.c", "main.c", "rtwrap.c", "vm.c", "ns.c", "nfns.c", "ffi.c"⟩
|
||||
⟨"src/jit/", "nvm.c"⟩
|
||||
⟨"src/utils/", "utf.c", "hash.c", "file.c", "mut.c", "each.c", "bits.c"⟩
|
||||
⟩
|
||||
singeliMap ← ⟨
|
||||
"src/core/stuff.c"‿"equal", "src/utils/mut.c"‿"copy", "src/utils/bits.c"‿"bits"
|
||||
"src/builtins/arithd.c"‿"dyarith", "src/builtins/cmp.c"‿"cmp", "src/builtins/squeeze.c"‿"squeeze"
|
||||
"src/builtins/select.c"‿"select", "src/builtins/fold.c"‿"fold", "src/builtins/scan.c"‿"scan"
|
||||
"src/builtins/scan.c"‿"neq", "src/builtins/slash.c"‿"slash", "src/builtins/slash.c"‿"constrep"
|
||||
⟩
|
||||
objs ← ⟨⟩
|
||||
|
||||
|
||||
|
||||
replxxCache ← {
|
||||
¬po.replxx? @;
|
||||
replxxCache ← GetCache ⟨"replxx", "REPLXX object file location", po.REPLXXc@⟩
|
||||
|
||||
replxxSrc ← (po.replxxDir•file.At"src")⊸•file.At¨⟨"ConvertUTF.cpp", "wcwidth.cpp", "conversion.cxx", "escape.cxx", "history.cxx", "prompt.cxx", "replxx.cxx", "replxx_impl.cxx", "terminal.cxx", "util.cxx", "windows.cxx"⟩
|
||||
objs∾↩ {𝕩.dst}¨ (Shorten replxxSrc) {MakeCCInv ⟨po.REPLXXc, ⊢, replxxCache, 𝕨, 𝕩, ⟨⟩⟩}¨ replxxSrc
|
||||
|
||||
replxxCache
|
||||
}
|
||||
|
||||
singeliObjs ← @
|
||||
singeliCache ← {
|
||||
¬po.singeli? @;
|
||||
singeliCache ← GetCache ⟨"singeli", "Singeli generated code location", ⟨po.native, po.arch⟩⟩
|
||||
|
||||
# genArithTables
|
||||
ga ← "src/singeli/src/genArithTables.bqn"
|
||||
gaDefs ← singeliCache.File "arDefs.singeli"
|
||||
gaTables ← singeliCache.File "arTables.c"
|
||||
AddRule ⟨
|
||||
singeliCache, "genArithTables",
|
||||
gaDefs, # am cheating and only using arDefs.singeli as destination; ¯\_(ツ)_/¯
|
||||
{𝕊: ⟨"runbqn", rootdir, AtRoot ga, AtRoot¨ gaDefs‿gaTables, ⟨ga⟩⟩},
|
||||
•file.Name ga, ⟨⟩
|
||||
⟩
|
||||
|
||||
singeliArgs ← ⟨"-l", "gen="∾singeliCache.folder⟩∾{
|
||||
po.native? ⟨⟩;
|
||||
"-a" ⋈ {"x86-64":"X86_64"; "aarch64":"AARCH64"} po.arch
|
||||
}
|
||||
singeliObjs ↩ {𝕩.dst}¨ {MakeSingeliInv ⟨singeliArgs, {𝕊:UpdateSubmodule po.singeliDir}, singeliCache, 𝕩, "src/singeli/src/"•file.At 𝕩∾".singeli", (𝕩≡"dyarith")/⟨gaDefs⟩⟩}¨ 1⊑¨singeliMap
|
||||
|
||||
singeliCache
|
||||
}
|
||||
|
||||
cbqnCache ← {
|
||||
cbqnCache ← GetCache ⟨"cbqn", "CBQN object file location", ⟨po.CBQNc@, {po.singeli? singeliCache.hash; @}⟩⟩
|
||||
ruleDeps ← {
|
||||
¬po.singeli? ⟨⟩¨ cbqnSrc;
|
||||
((≠cbqnSrc) ∾˜ cbqnSrc⊐⊑¨singeliMap) ⊔ singeliObjs
|
||||
}
|
||||
|
||||
singeliArgs ← {po.singeli? ⟨"-DSINGELI_DIR="∾•file.Name singeliCache.folder⟩; ⟨⟩}
|
||||
objs∾↩ {𝕩.dst}¨ {a‿b‿c: MakeCCInv ⟨po.CBQNc∾singeliArgs˙, {𝕊:UpdateSubmodule po.bytecodeDir ⋄ UpdateSubmodule po.replxxDir}, cbqnCache, a, b, c⟩}¨ <˘⍉[Shorten cbqnSrc, cbqnSrc, ruleDeps] # updates replxx because needs replxx.h
|
||||
|
||||
cbqnCache
|
||||
}
|
||||
|
||||
linkerCache ← GetCache ⟨"linker", "linker cached result location", ⟨
|
||||
po.Linker@,
|
||||
cbqnCache.hash,
|
||||
{po.replxx? replxxCache.hash; @}
|
||||
{po.singeli? singeliCache.hash; @}
|
||||
⟩⟩
|
||||
res ← MakeLinkerInv ⟨po.Linker, linkerCache, {po.emcc? "BQN.js"; "res"}, objs⟩
|
||||
|
||||
res.dst ⋈ linkerCache
|
||||
}
|
||||
|
||||
outPath ← •wdpath •file.At po.output
|
||||
{ 𝕊:
|
||||
po.emcc?
|
||||
SH ⟨"cp", AtRoot cachedBin, outPath •file.At •file.Name cachedBin⟩
|
||||
SH ⟨"cp", AtRoot linkerCache.File "BQN.wasm", outPath •file.At "BQN.wasm"⟩
|
||||
;
|
||||
SH ⟨"cp", AtRoot cachedBin, outPath⟩
|
||||
}⍟⊢ Run cachedBin
|
||||
|
||||
OnExit@
|
||||
110
build/src/fork.bqn
Normal file
110
build/src/fork.bqn
Normal file
@ -0,0 +1,110 @@
|
||||
sz←"u64" ⋄ ssz←"i64" ⋄ nfds←sz
|
||||
|
||||
libc_fork ← @ •FFI "i32"‿"fork"
|
||||
libc_pipe ← @ •FFI "i32"‿"pipe"‿">&i32"
|
||||
libc_read ← @ •FFI ssz‿"read"‿"i32"‿"&i8"‿sz
|
||||
libc_write ← @ •FFI ssz‿"write"‿"i32"‿"*i8"‿sz
|
||||
libc_close ← @ •FFI "i32"‿"close"‿">i32"
|
||||
libc_poll ← @ •FFI "i32"‿"poll"‿"&i16"‿nfds‿"i32"
|
||||
|
||||
Pipe ← { 𝕊: readfd‿writefd ⇐
|
||||
⟨c, readfd‿writefd⟩ ← Libc_pipe 0‿0
|
||||
! c=0
|
||||
Write ⇐ {Libc_write ⟨writefd, 𝕩, ≠𝕩⟩}
|
||||
Read ⇐ {n‿b ← Libc_read ⟨readfd, 𝕩⥊0, 𝕩⟩ ⋄ !n≥0 ⋄ n↑b}
|
||||
}
|
||||
|
||||
BiDiFork ← { 𝕊:
|
||||
p1 ← Pipe@
|
||||
p2 ← Pipe@
|
||||
pid ⇐ Libc_fork@
|
||||
! pid≥0
|
||||
parent ⇐ pid=0
|
||||
CloseWR ← {! ¬∨´ Libc_close¨ {𝕨.writefd‿𝕩.readfd}´ ⌽⍟parent 𝕩}
|
||||
CloseWR p1‿p2
|
||||
r‿w ⇐ ⌽⍟parent p1‿p2
|
||||
Read‿readfd ⇐ r
|
||||
Write‿writefd ⇐ w
|
||||
Close ⇐ CloseWR∘p2‿p1
|
||||
}
|
||||
|
||||
FFn ← { 𝕊 fn:
|
||||
f ← BiDiFork@
|
||||
{f.parent? Fn f ⋄ f.Close@ ⋄ •Exit 0; f}
|
||||
}
|
||||
|
||||
WriteAll ← {p𝕊x: {𝕩-p.Write 𝕩-⊸↑x}•_while_× ≠x}
|
||||
_readAll ← {p E _𝕣 n: ⊑⍟(¬=) {v←p.Read n-≠𝕩 ⋄ 0<≠v? 𝕩∾v; <E"eof"}•_while_(=∧n≠≠) ↕0}
|
||||
|
||||
WriteSz ← {
|
||||
𝕨 WriteAll (32‿8•bit._cast ⋈≠𝕩)∾𝕩
|
||||
}
|
||||
_readSz ← { 𝔽_𝕣 s:
|
||||
r ← s <∘𝔽 _readAll 4
|
||||
{
|
||||
=r? n ← ⊑8‿32•bit._cast r ⋄ s !_readAll n;
|
||||
⊑r
|
||||
}
|
||||
}
|
||||
|
||||
Serialize‿Deserialize ← •Import "serialize.bqn"
|
||||
|
||||
c_make ← 1
|
||||
c_request ← 2
|
||||
c_take ← 3
|
||||
c_one ← 4
|
||||
|
||||
control ← FFn {{ 𝕊 control:
|
||||
pids‿procs ← ⋈˜⟨⟩
|
||||
{𝕊:
|
||||
ty‿cmd ← Deserialize •Exit _readSz control
|
||||
|
||||
ty◶⟨ !
|
||||
{ 𝕊program: # c_make
|
||||
p ← FFn {{ 𝕊 p:
|
||||
f ← ⟨•file.Parent program, •file.Name program⟩ •BQN •FChars program
|
||||
{𝕊: p WriteSz Serialize F Deserialize •Exit _readSz p}•_while_ 1@
|
||||
}}
|
||||
control WriteAll 32‿8•bit._cast ⋈p.pid
|
||||
pids∾↩ <p.pid
|
||||
procs∾↩ <p
|
||||
}
|
||||
{ 𝕊pid‿data: # c_request
|
||||
p ← (⊑pids⊐pid)⊑procs
|
||||
p WriteSz data
|
||||
}
|
||||
{ 𝕊pid: # c_take
|
||||
p ← (⊑pids⊐pid)⊑procs
|
||||
control WriteSz !_readSz p
|
||||
}
|
||||
{ 𝕊limit‿sel: # c_one
|
||||
ms ← limit×1e3
|
||||
"poll time limit too large" ! (ms≡∞) ∨ ms<2⋆31
|
||||
p ← (pids⊐sel)⊏procs
|
||||
fds ← {𝕩.readfd}¨ p
|
||||
ret‿res ← Libc_poll ⟨⥊ ∾⟜1‿0˘ 32‿16•bit._cast ≍˘fds ⋄ ≠fds ⋄ ∞⊸≡◶⌊‿¯1 ms⟩
|
||||
! ret≥0
|
||||
control WriteSz Serialize {¯1¨⌾((¬𝕩∊0‿1)⊸/)𝕩} ¯1⊏˘∘‿4⥊res
|
||||
}
|
||||
⟩ cmd
|
||||
}•_while_ 1@
|
||||
}}
|
||||
AskControl ← {control WriteSz Serialize 𝕨‿𝕩}
|
||||
|
||||
Spawn ⇐ {
|
||||
c_make AskControl 𝕩
|
||||
pid ← ⊑8‿32•bit._cast control !_readAll 4
|
||||
{
|
||||
pid⇐pid
|
||||
Request ⇐ {c_request AskControl pid⋈Serialize 𝕩}
|
||||
Take ⇐ {𝕊: c_take AskControl pid ⋄ Deserialize !_readSz control}
|
||||
}
|
||||
}
|
||||
|
||||
# 𝕩: list of spawn results to wait on
|
||||
# 𝕨: if present, maximum time to wait; 0 to return immediately
|
||||
# result: boolean mask of which have finished (if 𝕨 isn't given, guaranteed to have at least one `1`)
|
||||
WaitForOne ⇐ {
|
||||
c_one AskControl ⟨𝕨⊣∞ ⋄ {𝕩.pid}¨ 𝕩⟩
|
||||
Deserialize !_readSz control
|
||||
}
|
||||
57
build/src/runner.bqn
Normal file
57
build/src/runner.bqn
Normal file
@ -0,0 +1,57 @@
|
||||
chdir ← @•FFI"i32"‿"chdir"‿">*u8:c8"
|
||||
Split ← {𝕩⊔˜(⊢-˜+`׬)𝕩=𝕨}
|
||||
SimplifyPath ← {
|
||||
1↓∾'/'⊸∾¨ {(∊××) ⌊`⌾⌽ +` ¬⊸- ".."⊸≡¨𝕩}⊸/ "."⊸≢¨⊸/ '/'Split𝕩
|
||||
}
|
||||
Good ← { 𝕊 dir‿t0‿t1‿o‿e‿deps:
|
||||
⟨1, o∾e, t1-t0, deps ⋈¨ (•file.Modified dir•file.At⊢)¨ deps⟩
|
||||
}
|
||||
|
||||
_runSingeli_ ← { runArgs GetDeps _𝕣_ dir runFile:
|
||||
t0 ← •MonoTime@
|
||||
e←@ ⋄ deps←@
|
||||
{𝕊:
|
||||
runArgs •Import runFile
|
||||
deps ↩ GetDeps@
|
||||
}⎊{𝕊: e↩•CurrentError@} @
|
||||
t1 ← •MonoTime@
|
||||
{
|
||||
e≢@? ⟨0, e⟩;
|
||||
Good ⟨dir,t0,t1,"","",deps⟩
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"sh"‿dir‿cmd‿depf:
|
||||
t0 ← •MonoTime@
|
||||
Chdir @∾˜ •ToUTF8 dir
|
||||
c‿o‿e ← •SH cmd
|
||||
t1 ← •MonoTime@
|
||||
{
|
||||
0: @≡depf?
|
||||
Good ⟨dir,t0,t1,o,e,⟨⟩⟩;
|
||||
0:
|
||||
deps ← •FLines depf
|
||||
deps {𝕩/˜1»∧`'\'=¯1⊑∘↑¨𝕩}↩ # remove all but the initial rule
|
||||
deps {𝕩↓˜1+⊑𝕩⊐':'}⌾⊑↩ # remove rule name
|
||||
deps ¯1⊸↓¨⌾(¯1↓⊢)↩ # remove trailing backslashes
|
||||
deps ({𝕩/˜¬∧`𝕩=' '}⌽)⍟2¨↩ # trim whitespace from both sides
|
||||
deps (∾' 'Split¨⊢)↩ # split each on spaces
|
||||
deps {¬∨´"/build/obj2/"⍷𝕩}¨⊸/↩ # remove autogenerated dependencies, those are handled manually
|
||||
deps SimplifyPath¨↩ # remove "."s & ".."s
|
||||
deps {dir<○≠𝕩? dir≡(≠dir)↑𝕩? (≠dir)↓𝕩; 𝕩}¨↩ # relativize
|
||||
Good ⟨dir,t0,t1,o,e,deps⟩;
|
||||
# c≠0:
|
||||
⟨0, o∾e⟩
|
||||
} c
|
||||
;
|
||||
"singeli"‿dir‿dst‿singeliDir‿args‿src‿dep:
|
||||
prefix ← "si_"∾ (∧`'.'⊸≠)⊸/ •file.Name src
|
||||
argsFinal ← args∾⟨"-d" ⋄ dep ⋄ "-o" ⋄ dst ⋄ "-n" ⋄ prefix ⋄ src⟩
|
||||
argsFinal {𝕊: src<⊸∾ SimplifyPath¨ singeliDir⊸•file.At¨ •FLines dep}_runSingeli_ dir singeliDir •file.At "singeli"
|
||||
;
|
||||
"runbqn"‿dir‿file‿args‿deps:
|
||||
args deps _runSingeli_ dir file
|
||||
;
|
||||
0⋈"unknown command"
|
||||
}
|
||||
54
build/src/serialize.bqn
Normal file
54
build/src/serialize.bqn
Normal file
@ -0,0 +1,54 @@
|
||||
eltype2bit ← ⟨1,8,16,32,64,8‿'c',16‿'c',32‿'c'⟩
|
||||
eltypeWidth ← ⟨1,1,2,4,8,1,2,4⟩
|
||||
|
||||
SStep ← •Type◶⟨
|
||||
{
|
||||
𝕩 •internal.Squeeze↩
|
||||
eltype ← •internal.ElType𝕩
|
||||
×∘≠¨⊸/ ⟨
|
||||
⟨0, eltype⟩
|
||||
32‿8•bit._cast ⋈=𝕩
|
||||
64‿8•bit._cast ≢𝕩
|
||||
{
|
||||
eltype=8? SStep¨ ⥊𝕩;
|
||||
⟨eltype⊑eltype2bit, 8⟩•bit._cast (8×·⌈≠÷8˙)⊸↑⍟(0=eltype) ⥊𝕩
|
||||
}𝕩
|
||||
⟩
|
||||
}
|
||||
{ ⟨⟨1⟩, 64‿8•bit._cast⋈𝕩⟩ }
|
||||
{ ⟨⟨2⟩, 32‿8•bit._cast⋈𝕩⟩ }
|
||||
{𝕊:!"Cannot serialize functions"}
|
||||
{𝕊:!"Cannot serialize 1-modifiers"}
|
||||
{𝕊:!"Cannot serialize 2-modifiers"}
|
||||
{𝕊:!"Cannot serialize namespaces"}
|
||||
⟩
|
||||
|
||||
Serialize ⇐ {
|
||||
lists ← ⟨⟩
|
||||
{0=•Type⊑𝕩? 𝕊¨𝕩; lists∾↩<𝕩 ⋄ 1} SStep 𝕩
|
||||
∾lists
|
||||
}
|
||||
Deserialize ⇐ {
|
||||
s←𝕩
|
||||
off←0
|
||||
Next ← {r←𝕩↑off↓s ⋄ off+↩𝕩 ⋄ r}
|
||||
Read ← { 𝕊:
|
||||
type ← ⊑Next 1
|
||||
type◶⟨
|
||||
{𝕊:
|
||||
et ← ⊑Next 1
|
||||
rank ← ⊑8‿32•bit._cast Next 4
|
||||
shape ← 8‿64•bit._cast Next rank×8
|
||||
shape⥊{
|
||||
et=8? Read¨ ↕×´shape;
|
||||
⟨8, et⊑eltype2bit⟩•bit._cast Next (⌈÷⟜8)⍟(0=et) (et⊑eltypeWidth)×´shape
|
||||
}
|
||||
}
|
||||
{𝕊: ⊑⟨8, 64 ⟩•bit._cast Next 8}
|
||||
{𝕊: ⊑⟨8, 32‿'c'⟩•bit._cast Next 4}
|
||||
⟩@
|
||||
}
|
||||
r ← Read@
|
||||
off=≠s? r;
|
||||
! "invalid input: data after end"
|
||||
}
|
||||
5
makefile
5
makefile
@ -37,6 +37,8 @@ shared-o3:
|
||||
@${MAKE} i_OUTPUT=libcbqn.so i_SHARED=1 i_t=shared_o3 i_f="-O3" run_incremental_0
|
||||
shared-c:
|
||||
@${MAKE} i_OUTPUT=libcbqn.so i_SHARED=1 custom=1 run_incremental_0
|
||||
forbuild:
|
||||
@${MAKE} i_singeli=0 i_t=forbuild i_f="-O2" i_FFI=2 i_OUTPUT=build/obj2/for_build i_f='-DFOR_BUILD' run_incremental_0
|
||||
c:
|
||||
@${MAKE} custom=1 run_incremental_0
|
||||
|
||||
@ -179,6 +181,9 @@ single-c:
|
||||
|
||||
# actual build
|
||||
run_incremental_0:
|
||||
ifeq ($(i_t),forbuild)
|
||||
mkdir -p build/obj2
|
||||
endif
|
||||
ifeq ($(verbose),1)
|
||||
@echo "build directory: $$(${MAKE} builddir)"
|
||||
@echo " bytecode: build/$(BYTECODE_DIR)"
|
||||
|
||||
@ -352,4 +352,5 @@ static NOINLINE B or_SA(B t, B w, B x) {
|
||||
return r;
|
||||
}
|
||||
|
||||
#include "../gen/arTables.c"
|
||||
#define SINGELI_FILE arTables
|
||||
#include "../../utils/includeSingeli.h"
|
||||
|
||||
@ -189,4 +189,4 @@ andBytes{vw}(r: *u8, x: *u8, maskU64:u64, len:u64) : void = {
|
||||
|
||||
'avx2_andBytes'=andBytes{256}
|
||||
'orSAc_f64_f64_f64'=arithSA{2,bqn_or,0,f64,f64,f64}
|
||||
include './../gen/arDefs'
|
||||
include 'gen/arDefs'
|
||||
|
||||
@ -19,7 +19,11 @@
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#ifdef SINGELI_DIR
|
||||
#include SINGELI_FILE1(../../build/obj2/SINGELI_DIR/SINGELI_FILE.c)
|
||||
#else
|
||||
#include SINGELI_FILE1(../singeli/gen/SINGELI_FILE.c)
|
||||
#endif
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#undef SINGELI_FILE
|
||||
Loading…
Reference in New Issue
Block a user