•args, •FLines, command-line options, •Repr, fix unit∾unit fill

This commit is contained in:
dzaima 2021-05-15 17:51:17 +03:00
parent 915b84f028
commit c2013e3b5d
11 changed files with 221 additions and 94 deletions

17
cc.bqn
View File

@ -7,8 +7,8 @@ return ← 1≡⊑args
args˜ return
path(args)"/src/"
args˜1
L {"m_caB(" (𝕩)",(B[]){" (1","¨𝕩)"})"}
LI {"m_cai32("(𝕩)",(i32[]){"(1","¨𝕩)"})"}
L {"m_caB(" (•Repr𝕩)",(B[]){" (1","¨𝕩)"})"}
LI {"m_cai32("(•Repr𝕩)",(i32[]){"(1","¨𝕩)"})"}
# Escape the special characters that appear in BQN sources.
Esc{
in (@+091013)"'""" # Null, Tab, LF, CR, and quotes
@ -19,9 +19,9 @@ Esc←{
}
Str "m_str32(U"""Esc""")"˙ # A BQN string
Char {"m_c32(U'"(Esc𝕩)"')"} # A BQN character
Num {s"-"/˜𝕩<0 =|"m_f64("")"˜s| "m_f64("s"1.0/0.0)"𝕩} # Format number
Num {s"-"/˜𝕩<0 =|"m_f64("")"˜s•Repr| "m_f64("s"1.0/0.0)"𝕩} # Format number
F # Format number
F •Repr # Format number
Import {𝕨•Import path𝕩}
FChars {𝕨•FChars path𝕩}
@ -30,12 +30,13 @@ FLines ← {𝕨•FLines path∾𝕩}
glyphs Import "glyphs.bqn"
_getComp { (3+useInd) (𝕗 Import "c.bqn"){𝔽} }
useInd "-i"args args˜useInd
Comp ((<"inc(runtime[""])"˙)¨62) glyphs _getComp
J \n¨
Comp ((<"inc(runtime["•Repr"])"˙)¨62) glyphs _getComp
J (@+10)¨
Fconst @NumChar, Str,
Fout {((𝕩)LI F¨,L Fconst¨,L (LI ·F¨ 4)¨,L (L F¨)¨) {𝕎𝕩}¨ 𝕩}
Frun 1Fout
Long {¯2𝕩¨<","\n}
Long {¯2𝕩¨<","@+10}
LFC LongFoutComp
RT {
srcneedinputs𝕩Import"pr.bqn"
@ -43,7 +44,7 @@ RT ← {
Long Fout pr need _getComp src
}
CArg {J (¯5𝕩˙) FLines "c.bqn"}
LFC LongFoutComp
SVG {"Modify←GetHighlights←⊢⋄" FChars".bqn"¨ "../svg"𝕩}
•Out(¬return) ("r""r0""r1""c""cc""f""e""p")
RT2, RT0, RT1

View File

@ -6,11 +6,7 @@ typedef struct FillArr {
B a[];
} FillArr;
B getFillQ(B x) { // doesn't consume; can return bi_noFill
bool defZero = true;
#ifdef CATCH_ERRORS
defZero = false;
#endif
B getFillR(B x) { // doesn't consume; can return bi_noFill
if (isArr(x)) {
u8 t = v(x)->type;
if (t==t_fillarr ) { B r = inc(c(FillArr,x )->fill); return r; }
@ -18,12 +14,18 @@ B getFillQ(B x) { // doesn't consume; can return bi_noFill
if (t==t_c32arr || t==t_c32slice) return m_c32(' ');
if (t==t_i32arr || t==t_i32slice) return m_f64(0 );
if (t==t_f64arr || t==t_f64slice) return m_f64(0 );
return defZero? m_f64(0) : bi_noFill;
return bi_noFill;
}
if (isF64(x)|isI32(x)) return m_i32(0);
if (isC32(x)) return m_c32(' ');
return defZero? m_f64(0) : bi_noFill;
return bi_noFill;
}
B getFillQ(B x) { // doesn't consume; can return bi_noFill if CATCH_ERRORS
B r = getFillR(x);
#ifdef CATCH_ERRORS
return r;
#endif
return noFill(r)? m_f64(0) : r;
}
B getFillE(B x) { // errors if there's no fill
B xf = getFillQ(x);

View File

@ -81,13 +81,6 @@ B ltack_c2(B t, B w, B x) { dec(x); return w; }
B rtack_c1(B t, B x) { return x; }
B rtack_c2(B t, B w, B x) { dec(w); return x; }
B fmtN_c1(B t, B x) {
#define BL 100
char buf[BL];
if (isF64(x)) snprintf(buf, BL, "%g", x.f);
else snprintf(buf, BL, "(fmtN: not given a number?)");
return m_str8(strlen(buf), buf);
}
B fmtF_c1(B t, B x) {
if (!isVal(x)) return m_str32(U"(fmtF: not given a function)");
u8 fl = v(x)->flags;
@ -180,7 +173,7 @@ B fne_c2(B t, B w, B x) {
#define BI_FNS1(F) F(BI_A,BI_M,BI_D)
#define F(A,M,D) A(ud) A(fne) A(feq) A(ltack) A(rtack) M(fmtF) M(fmtN)
#define F(A,M,D) A(ud) A(fne) A(feq) A(ltack) A(rtack) M(fmtF)
BI_FNS0(F);
static inline void fns_init() { BI_FNS1(F)
ti[t_funBI].print = print_funBI;

12
src/h.h
View File

@ -123,11 +123,11 @@ char* format_type(u8 u) {
#define FOR_PF(F) F(none, "(unknown fn)") \
/*arith.c*/ F(add,"+") F(sub,"-") F(mul,"×") F(div,"÷") F(pow,"") F(floor,"") F(ceil,"") F(stile,"|") F(eq,"=") \
/*arith.c*/ F(ne,"") F(le,"") F(ge,"") F(lt,"<") F(gt,">") F(and,"") F(or,"") F(not,"¬") F(log,"⋆⁼") \
/*fns.c*/ F(ud,"") F(fne,"") F(feq,"") F(ltack,"") F(rtack,"") F(fmtF,"•FmtF") F(fmtN,"•FmtN") \
/*fns.c*/ F(ud,"") F(fne,"") F(feq,"") F(ltack,"") F(rtack,"") F(fmtF,"•FmtF") \
/*sfns.c*/ F(shape,"") F(pick,"") F(pair,"{𝕨‿𝕩}") F(select,"") F(slash,"/") F(join,"") F(couple,"") F(shiftb,"»") F(shifta,"«") F(take,"") F(drop,"") F(group,"") \
/*derv.c*/ F(fork,"(fork)") F(atop,"(atop)") F(md1d,"(derived 1-modifier)") F(md2d,"(derived 2-modifier)") \
/*sort.c*/ F(gradeUp,"") \
/*sysfn.c*/ F(type,"•Type") F(decp,"•Decompose") F(primInd,"•PrimInd") F(glyph,"•Glyph") F(fill,"•FillFn") \
/*sysfn.c*/ F(type,"•Type") F(decp,"•Decompose") F(primInd,"•PrimInd") F(glyph,"•Glyph") F(repr,"•Repr") F(fill,"•FillFn") \
/*sysfn.c*/ F(grLen,"•GroupLen") F(grOrd,"•groupOrd") F(asrt,"!") F(sys,"•getsys") F(bqn,"•BQN") F(cmp,"•Cmp") F(internal,"•Internal") F(show,"•Show") F(out,"•Out") \
enum PrimFns {
@ -145,13 +145,13 @@ char* format_pf(u8 u) {
enum PrimMd1 {
pm1_none,
pm1_tbl, pm1_each, pm1_fold, pm1_scan, pm1_const, pm1_swap, pm1_timed, // md1.c
pm1_fchars, pm1_fbytes, pm1_import, // md1.c
pm1_fchars, pm1_fbytes, pm1_flines, pm1_import, // md1.c
};
char* format_pm1(u8 u) {
switch(u) {
default: case pf_none: return"(unknown 1-modifier)";
case pm1_tbl:return""; case pm1_each:return"¨"; case pm1_fold:return"´"; case pm1_scan:return"`"; case pm1_const:return"˙"; case pm1_swap:return"˜"; case pm1_timed:return"•_timed";
case pm1_fchars:return"•FChars"; case pm1_fbytes:return"•FBytes"; case pm1_import:return"•Import";
case pm1_fchars:return"•FChars"; case pm1_fbytes:return"•FBytes"; case pm1_flines:return"•FLines"; case pm1_import:return"•Import";
}
}
enum PrimMd2 {
@ -258,8 +258,8 @@ B m_unit (B x); // consumes
B m_hunit(B x); // consumes
B m_str32(u32* s); // meant to be used as m_str32(U"{𝕨‿𝕩}"), so doesn't free for you
B bqn_exec(B str, B path); // consumes both
B bqn_execFile(B path); // consumes
B bqn_exec(B str, B path, B args); // consumes both
B bqn_execFile(B path, B args); // consumes
NOINLINE NORETURN void thr(B b);
NOINLINE NORETURN void thrM(char* s);

View File

@ -23,17 +23,22 @@ B bqn_fmt(B x) { // consumes
}
#endif
void load_gcFn() { mm_visit(comp_currPath); }
Block* bqn_comp(B str, B path) { // consumes both
void load_gcFn() {
mm_visit(comp_currPath);
mm_visit(comp_currArgs);
}
Block* bqn_comp(B str, B path, B args) { // consumes all
comp_currPath = path;
comp_currArgs = args;
Block* r = load_compObj(c2(load_comp, inc(load_compArg), inc(str)), str);
dec(path);
comp_currPath = bi_N;
dec(path); dec(args);
comp_currArgs = comp_currPath = bi_N;
return r;
}
B bqn_exec(B str, B path) { // consumes both
Block* block = bqn_comp(str, path);
B bqn_exec(B str, B path, B args) { // consumes all
Block* block = bqn_comp(str, path, args);
B res = m_funBlock(block, 0);
ptr_dec(block);
return res;
@ -45,6 +50,7 @@ void bqn_setComp(B comp) { // consumes; doesn't unload old comp, but whatever
static inline void load_init() {
comp_currPath = bi_N;
comp_currArgs = bi_N;
gc_addFn(load_gcFn);
B fruntime[] = {
/* +-×÷⋆√⌊⌈|¬ */ bi_add , bi_sub , bi_mul , bi_div , bi_pow , bi_N , bi_floor, bi_ceil, bi_stile , bi_not,
@ -161,6 +167,6 @@ static inline void load_init() {
#endif // NO_COMP
}
B bqn_execFile(B path) { // consumes
return bqn_exec(file_chars(inc(path)), path);
B bqn_execFile(B path, B args) { // consumes both
return bqn_exec(file_chars(inc(path)), path, args);
}

View File

@ -81,8 +81,77 @@ int main(int argc, char* argv[]) {
exit(1);
}
#endif
if (argc==1) {
bool startREPL = argc==1;
if (!startREPL) {
i32 i = 1;
while (i!=argc) {
char* carg = argv[i];
if (carg[0]!='-') break;
i++;
if (carg[1]=='-') {
if (!strcmp(carg, "--help")) {
printf(
"Usage: %s [options] [file.bqn [arguments]]\n"
"Options:\n"
"-f file: execute the contents of the file with all further arguments as •args\n"
"-e code: execute the argument as BQN\n"
"-p code: execute the argument as BQN and print its result pretty-printed\n"
"-o code: execute the argument as BQN and print its raw result\n"
"-r : start the REPL after all further arguments\n"
, argv[0]);
exit(0);
} else {
printf("%s: Unknown option: %s\n", argv[0], carg);
exit(1);
}
} else {
carg++;
char c;
while ((c=*carg++) != '\0') {
switch(c) { default: printf("Unknown option: -%c\n", c);
#define REQARG(X) if(*carg) { printf("%s: -%s must end the option\n", argv[0], #X); exit(1); } if (i==argc) { printf("%s: -%s requires an argument\n", argv[0], #X); exit(1); }
case 'f': REQARG(f); goto execFile;
case 'e': { REQARG(e);
dec(bqn_exec(fromUTF8l(argv[i++]), m_str32(U"-e"), inc(bi_emptyHVec)));
break;
}
case 'p': { REQARG(p);
B r = bqn_exec(fromUTF8l(argv[i++]), m_str32(U"-e"), inc(bi_emptyHVec));
print(r); dec(r);
printf("\n");
break;
}
case 'o': { REQARG(o);
B r = bqn_exec(fromUTF8l(argv[i++]), m_str32(U"-e"), inc(bi_emptyHVec));
printRaw(r); dec(r);
printf("\n");
break;
}
case 'r': {
startREPL = true;
break;
}
}
}
}
}
execFile:
if (i!=argc) {
B src = fromUTF8l(argv[i++]);
B args;
if (i==argc) {
args = inc(bi_emptyHVec);
} else {
HArr_p ap = m_harrUv(argc-i); // eh whatever, erroring will exit anyways
for (usz j = 0; j < argc-i; j++) {
ap.a[j] = fromUTF8l(argv[i+j]);
}
args = ap.b;
}
dec(bqn_execFile(src, args));
}
}
if (startREPL) {
while (CATCH) {
printf("Error: "); print(catchMessage); putchar('\n');
vm_pst(envCurr, envStart+envPrevHeight);
@ -94,7 +163,7 @@ int main(int argc, char* argv[]) {
size_t gl = 0;
getline(&ln, &gl, stdin);
if (ln[0]==0 || ln[0]==10) break;
Block* block = bqn_comp(fromUTF8(ln, strlen(ln)), inc(replPath));
Block* block = bqn_comp(fromUTF8(ln, strlen(ln)), inc(replPath), inc(bi_emptyHVec));
free(ln);
#ifdef TIME
@ -124,8 +193,6 @@ int main(int argc, char* argv[]) {
#endif
}
popCatch();
} else {
bqn_execFile(fromUTF8l(argv[1]));
}
rtPerf_print();
CTR_FOR(CTR_PRINT)

View File

@ -215,14 +215,42 @@ B fchars_c1(B d, B x) { B f = c(Md1D,d)->f;
return file_chars(path_resolve(f, x));
}
B fbytes_c1(B d, B x) { B f = c(Md1D,d)->f;
TmpFile* tf = file_bytes(path_resolve(f, x)); usz ia = tf->ia; u8* p = (u8*)tf->a;
TmpFile* tf = file_bytes(path_resolve(f, x));
usz ia = tf->ia; u8* p = (u8*)tf->a;
u32* rp; B r = m_c32arrv(&rp, ia);
for (i64 i = 0; i < ia; i++) rp[i] = p[i];
ptr_dec(tf);
return r;
}
B flines_c1(B d, B x) { B f = c(Md1D,d)->f;
TmpFile* tf = file_bytes(path_resolve(f, x));
usz ia = tf->ia; u8* p = (u8*)tf->a;
usz lineCount = 0;
for (usz i = 0; i < ia; i++) {
if (p[i]=='\n') lineCount++;
else if (p[i]=='\r') {
lineCount++;
if(i+1<ia && p[i+1]=='\n') i++;
}
}
if (ia && (p[ia-1]!='\n' && p[ia-1]!='\r')) lineCount++;
usz i = 0;
HArr_p r = m_harrs(lineCount, &i);
usz pos = 0;
while (i < lineCount) {
usz spos = pos;
while(p[pos]!='\n' && p[pos]!='\r') pos++;
r.a[i++] = fromUTF8((char*)p+spos, pos-spos);
if (p[pos]=='\r' && pos+1<ia && p[pos+1]=='\n') pos+= 2;
else pos++;
}
return harr_fv(r);
}
B import_c1(B d, B x) { B f = c(Md1D,d)->f;
return bqn_execFile(path_resolve(f, x));
return bqn_execFile(path_resolve(f, x), inc(bi_emptyHVec));
}
B import_c2(B d, B w, B x) { B f = c(Md1D,d)->f;
return bqn_execFile(path_resolve(f, x), w);
}
#define ba(NAME) bi_##NAME = mm_alloc(sizeof(Md1), t_md1BI, ftag(MD1_TAG)); c(Md1,bi_##NAME)->c2 = NAME##_c2; c(Md1,bi_##NAME)->c1 = NAME##_c1 ; c(Md1,bi_##NAME)->extra=pm1_##NAME; gc_add(bi_##NAME);
@ -231,8 +259,8 @@ B import_c1(B d, B x) { B f = c(Md1D,d)->f;
void print_md1BI(B x) { printf("%s", format_pm1(c(Md1,x)->extra)); }
B bi_tbl, bi_each, bi_fold, bi_scan, bi_const, bi_swap, bi_timed, bi_fchars, bi_fbytes, bi_import;
static inline void md1_init() { ba(tbl) ba(each) ba(fold) ba(scan) ba(const) ba(swap) ba(timed) bm(fchars) bm(fbytes) bm(import)
B bi_tbl, bi_each, bi_fold, bi_scan, bi_const, bi_swap, bi_timed, bi_fchars, bi_fbytes, bi_flines, bi_import;
static inline void md1_init() { ba(tbl) ba(each) ba(fold) ba(scan) ba(const) ba(swap) ba(timed) bm(fchars) bm(fbytes) bm(flines) ba(import)
ti[t_md1BI].print = print_md1BI;
}

View File

@ -430,8 +430,19 @@ B join_c1(B t, B x) {
if (rnk(x)==1) {
usz xia = a(x)->ia;
if (xia==0) {
B xf = getFillE(x); dec(x);
if (isAtm(xf)) thrM("∾: Empty vector 𝕩 cannot have an atom fill element");
B xf = getFillE(x);
if (isAtm(xf)) {
decR(xf);
if (!PROPER_FILLS) {
B xfq = getFillR(x);
bool no = noFill(xfq);
decR(xfq);
if (no) return x;
}
dec(x);
thrM("∾: Empty vector 𝕩 cannot have an atom fill element");
}
dec(x);
ur ir = rnk(xf);
if (ir==0) thrM("∾: Empty vector 𝕩 cannot have a unit fill element");
B xff = getFillQ(xf);
@ -493,7 +504,7 @@ B join_c2(B t, B w, B x) {
HArr_p r = m_harrUv(2);
r.a[0] = TI(w).get(w,0); dec(w);
r.a[1] = TI(x).get(x,0); dec(x);
return r.b;
return withFill(r.b, f);
}
if (c-wr > 1 || c-xr > 1) thrM("∾: Argument ranks must differ by 1 or less");
MAKE_MUT(r, wia+xia);

View File

@ -365,6 +365,7 @@ void printAllocStats() {
}
_Thread_local B comp_currPath;
_Thread_local B comp_currArgs;
#define FOR_INIT(F) F(hdr) F(harr) F(fillarr) F(i32arr) F(c32arr) F(f64arr) F(fns) F(sfns) F(arith) F(grade) F(md1) F(md2) F(sysfn) F(derv) F(comp) F(rtPerf) F(ns) F(load)
#define F(X) static inline void X##_init();
FOR_INIT(F)

View File

@ -32,6 +32,14 @@ B glyph_c1(B t, B x) {
return x;
}
B repr_c1(B t, B x) {
#define BL 100
char buf[BL];
if (isF64(x)) snprintf(buf, BL, "%g", x.f);
else snprintf(buf, BL, "(fmtN: not given a number?)");
return m_str8(strlen(buf), buf);
}
B fill_c1(B t, B x) {
B r = getFillE(x);
dec(x);
@ -137,7 +145,7 @@ B bqn_c1(B t, B x) {
BS2B xgetU = TI(x).getU;
for (usz i = 0; i < ia; i++) if (!isC32(xgetU(x,i))) thrM("•BQN: Argument must be a character vector");
}
return bqn_exec(x, bi_N);
return bqn_exec(x, bi_N, bi_N);
}
B cmp_c2(B t, B w, B x) {
@ -147,7 +155,7 @@ B cmp_c2(B t, B w, B x) {
}
#define F(A,M,D) M(type) M(decp) M(primInd) M(glyph) A(fill) A(grLen) D(grOrd) A(asrt) M(out) M(show) M(sys) M(bqn) D(cmp) D(internal)
#define F(A,M,D) M(type) M(decp) M(primInd) M(glyph) M(repr) A(fill) A(grLen) D(grOrd) A(asrt) M(out) M(show) M(sys) M(bqn) D(cmp) D(internal)
BI_FNS0(F);
static inline void sysfn_init() { BI_FNS1(F) }
#undef F
@ -156,7 +164,7 @@ static B makeRel(B md) { // doesn't consume
return m1_d(inc(md), path_dir(inc(comp_currPath)));
}
B bi_timed, bi_fchars, bi_fbytes, bi_import;
B bi_timed, bi_fchars, bi_fbytes, bi_flines, bi_import;
B sys_c1(B t, B x) {
assert(isArr(x));
usz i = 0;
@ -173,10 +181,15 @@ B sys_c1(B t, B x) {
else if (eqStr(c, U"bqn")) r.a[i] = inc(bi_bqn);
else if (eqStr(c, U"cmp")) r.a[i] = inc(bi_cmp);
else if (eqStr(c, U"timed")) r.a[i] = inc(bi_timed);
else if (eqStr(c, U"repr")) r.a[i] = inc(bi_repr);
else if (eqStr(c, U"fchars")) r.a[i] = makeRel(bi_fchars);
else if (eqStr(c, U"fbytes")) r.a[i] = makeRel(bi_fbytes);
else if (eqStr(c, U"flines")) r.a[i] = makeRel(bi_flines);
else if (eqStr(c, U"import")) r.a[i] = makeRel(bi_import);
else { dec(x); thrM("Unknown system function"); }
else if (eqStr(c, U"args")) {
if(isNothing(comp_currArgs)) thrM("No arguments present for •args");
r.a[i] = inc(comp_currArgs);
} else { dec(x); thrM("Unknown system function"); }
}
return harr_fcd(r, x);
}

View File

@ -685,46 +685,6 @@ void popCatch() {
#endif
}
NOINLINE NORETURN void thr(B msg) {
if (cf>cfStart) {
catchMessage = msg;
cf--;
B* gStackNew = gStackStart + cf->gsDepth;
assert(gStackNew<=gStack);
while (gStack!=gStackNew) dec(*--gStack);
envPrevHeight = envCurr-envStart;
Env* envNew = envStart + cf->envDepth;
assert(envNew<=envCurr);
while (envCurr!=envNew) {
envCurr--;
#if VM_POS
envCurr->bcV = *envCurr->bcP - i32arr_ptr(envCurr->sc->body->comp->bc) - 1;
#else
envCurr->bcV = envCurr->bcL - i32arr_ptr(envCurr->sc->body->comp->bc);
#endif
}
if (cfStart+cf->cfDepth > cf) err("bad catch cfDepth");
cf = cfStart+cf->cfDepth;
longjmp(cf->jmp, 1);
}
assert(cf==cfStart);
printf("Error: ");
print(msg);
puts("");
#ifdef DEBUG
__builtin_trap();
#else
exit(1);
#endif
}
NOINLINE NORETURN void thrM(char* s) {
thr(fromUTF8(s, strlen(s)));
}
NOINLINE NORETURN void thrOOM() { thrM("Out of memory"); }
NOINLINE void vm_pst(Env* s, Env* e) {
assert(s<=e);
@ -763,3 +723,48 @@ NOINLINE void vm_pst(Env* s, Env* e) {
i--;
}
}
static void unwindEnv(Env* envNew) {
assert(envNew<=envCurr);
while (envCurr!=envNew) {
envCurr--;
#if VM_POS
envCurr->bcV = *envCurr->bcP - i32arr_ptr(envCurr->sc->body->comp->bc) - 1;
#else
envCurr->bcV = envCurr->bcL - i32arr_ptr(envCurr->sc->body->comp->bc);
#endif
}
}
NOINLINE NORETURN void thr(B msg) {
if (cf>cfStart) {
catchMessage = msg;
cf--;
B* gStackNew = gStackStart + cf->gsDepth;
assert(gStackNew<=gStack);
while (gStack!=gStackNew) dec(*--gStack);
envPrevHeight = envCurr-envStart;
unwindEnv(envStart + cf->envDepth);
if (cfStart+cf->cfDepth > cf) err("bad catch cfDepth");
cf = cfStart+cf->cfDepth;
longjmp(cf->jmp, 1);
}
assert(cf==cfStart);
printf("Error: "); print(msg); putchar('\n');
Env* envPrev = envCurr;
unwindEnv(envStart);
vm_pst(envCurr, envPrev);
#ifdef DEBUG
__builtin_trap();
#else
exit(1);
#endif
}
NOINLINE NORETURN void thrM(char* s) {
thr(fromUTF8(s, strlen(s)));
}
NOINLINE NORETURN void thrOOM() { thrM("Out of memory"); }