IN: kernel
USE: ansi
-USE: win32-console
USE: alien
USE: compiler
USE: errors
! -no-<flag> CLI switch
t "user-init" set
t "interactive" set
- ! We don't want ANSI escape codes on Windows
- os "unix" = "ansi" set
t "compile" set
+ t "smart-terminal" set
! The first CLI arg is the image name.
cli-args uncons parse-command-line "image" set
- "ansi" get [ stdio [ <ansi-stream> ] change ] when
-
os "win32" = "compile" get and [
"kernel32" "kernel32.dll" "stdcall" add-library
"user32" "user32.dll" "stdcall" add-library
"compile" get [ compile-all ] when
- os "win32" = "compile" get and [
- stdio [ <win32-console-stream> ] change
+ "smart-terminal" get [
+ stdio smart-term-hook get change
] when
run-user-init ;
: type-union ( list list -- list )
append prune [ > ] sort ;
-: class\/ ( class class -- class )
+: class-or ( class class -- class )
#! Return a class that both classes are subclasses of.
swap builtin-supertypes
swap builtin-supertypes
type-union classes get hash [ object ] unless* ;
-: class/\ ( class class -- class )
+: class-and ( class class -- class )
#! Return a class that is a subclass of both, or raise an
#! error if this is impossible.
over builtin-supertypes
#! shorter, pad it with unknown results at the bottom.
dup longest-vector swap [ dupd add-inputs nip ] map nip ;
-: unify-results ( obj obj -- obj )
+: unify-classes ( value value -- value )
+ value-class swap value-class class-or <computed> ;
+
+: unify-results ( value value -- value )
#! Replace values with unknown result if they differ,
#! otherwise retain them.
- 2dup = [
- drop
- ] [
- value-class swap value-class class\/ <computed>
- ] ifte ;
+ 2dup = [ drop ] [ unify-classes ] ifte ;
: unify-stacks ( list -- stack )
#! Replace differing literals in stacks with unknown
#! Set base case if inference didn't fail.
[
f infer-branch [
- effect recursive-state get set-base
+ effect old-effect recursive-state get set-base
] bind
] [
[ drop ] when
meta-d get vector-tail* node-consume-d set ;
: dataflow-inputs ( in node -- )
- [ dup cons? [ length ] when 0 node-inputs ] bind ;
+ [ dup list? [ length ] when 0 node-inputs ] bind ;
: node-outputs ( d-count r-count -- )
#! Execute in the node's namespace.
meta-d get vector-tail* node-produce-d set ;
: dataflow-outputs ( out node -- )
- [ dup cons? [ length ] when 0 node-outputs ] bind ;
+ [ dup list? [ length ] when 0 node-outputs ] bind ;
: get-dataflow ( -- IR )
dataflow-graph get reverse ;
! - infer - quotation with custom inference behavior; ifte uses
! this. Word is passed on the stack.
-! Amount of results we had to add to the datastack
+! Vector of results we had to add to the datastack. Ie, the
+! inputs.
SYMBOL: d-in
! Recursive state. Alist maps words to hashmaps...
GENERIC: literal-value ( value -- obj )
GENERIC: value= ( literal value -- ? )
GENERIC: value-class ( value -- class )
+GENERIC: value-class-and ( class value -- )
TRAITS: computed
C: computed ( class -- value )
2drop f ;
M: computed value-class ( value -- class )
[ \ value-class get ] bind ;
+M: computed value-class-and ( class value -- )
+ [ \ value-class [ class-and ] change ] bind ;
TRAITS: literal
C: literal ( obj rstate -- value )
literal-value = ;
M: literal value-class ( value -- class )
literal-value class ;
+M: literal value-class-and ( class value -- )
+ value-class class-and drop ;
: value-recursion ( value -- rstate )
[ recursive-state get ] bind ;
+: (ensure-types) ( typelist n stack -- )
+ pick [
+ 3dup >r >r car r> r> vector-nth value-class-and
+ >r >r cdr r> succ r> (ensure-types)
+ ] [
+ 3drop
+ ] ifte ;
+
+: ensure-types ( typelist stack -- )
+ dup vector-length pick length - dup 0 < [
+ swap >r neg tail 0 r>
+ ] [
+ swap
+ ] ifte (ensure-types) ;
+
: required-inputs ( typelist stack -- values )
>r dup length r> vector-length - dup 0 > [
head [ <computed> ] map
>r list>vector dup r> vector-append ;
: ensure-d ( typelist -- )
+ dup meta-d get ensure-types
meta-d get required-inputs dup
meta-d [ vector-prepend ] change
d-in [ vector-prepend ] change ;
-: effect ( -- [ in | out ] )
+: effect ( -- [ in-types out-types ] )
#! After inference is finished, collect information.
- d-in get vector-length meta-d get vector-length cons ;
+ d-in get [ value-class ] vector-map vector>list
+ meta-d get [ value-class ] vector-map vector>list 2list ;
+
+: old-effect ( [ in-types out-types ] | [ in | out ] )
+ uncons car length >r length r> cons ;
: <recursive-state> ( -- state )
<namespace> [
- base-case off effect entry-effect set
+ base-case off effect old-effect entry-effect set
] extend ;
: init-inference ( recursive-state -- )
: dataflow ( quot -- dataflow )
#! Data flow of a quotation.
[ (infer) get-dataflow ] with-scope ;
-
-: type-infer ( quot -- [ in-types out-types ] )
- [
- (infer)
- d-in get [ value-class ] vector-map vector>list
- meta-d get [ value-class ] vector-map vector>list 2list
- ] with-scope ;
#! Take input parameters, execute quotation, take output
#! parameters, add node. The quotation is called with the
#! stack effect.
- >r dup car dup cons? [ [ drop object ] project ] unless ensure-d >r dataflow, r> r> rot
+ >r dup car dup list? [ [ drop object ] project ] unless ensure-d
+ >r dataflow, r> r> rot
[ pick car swap dataflow-inputs ] keep
- pick 2slip cdr swap
+ pick 2slip cdr dup cons? [ car ] when swap
dataflow-outputs ; inline
: consume-d ( typelist -- )
: (consume/produce) ( param op effect -- )
[
- dup cdr cons? [
+ dup cdr list? [
( new style )
unswons consume-d car produce-d
] [
] ifte
] with-dataflow ;
-: consume/produce ( word [ in | out ] -- )
+: consume/produce ( word [ in-types out-types ] -- )
#! Add a node to the dataflow graph that consumes and
#! produces a number of values.
#call swap (consume/produce) ;
-: apply-effect ( word [ in | out ] -- )
+: apply-effect ( word [ in-types out-types ] -- )
#! If a word does not have special inference behavior, we
#! either execute the word in the meta interpreter (if it is
#! side-effect-free and all parameters are literal), or
#! simply apply its stack effect to the meta-interpreter.
over "infer" word-property dup [
- swap car dup cons? [ [ drop object ] project ] unless ensure-d call drop
+ swap car dup list? [ [ drop object ] project ] unless ensure-d call drop
] [
drop consume/produce
] ifte ;
#! ansi-fg - foreground color
#! ansi-bg - background color
[ delegate set ] extend ;
+
+global [ [ <ansi-stream> ] smart-term-hook set ] bind
C: stdio-stream ( delegate -- stream )
[ delegate set ] extend ;
+
+! Set this to a quotation in init code, depending on OS.
+SYMBOL: smart-term-hook
USE: test
USE: vectors
USE: lists
+USE: words
! Various things that broke CFactor at various times.
! This should run without issue (and tests nothing useful)
[ callstack-overflow ] unit-test-fails
[ [ cdr cons ] word-plist ] unit-test-fails
+
+! Forgot to tag out of bounds index
+[ 1 { } vector-nth ] [ garbage-collection drop ] catch
+[ -1 { } set-vector-length ] [ garbage-collection drop ] catch
+[ 1 "" str-nth ] [ garbage-collection drop ] catch
[ 1/4 ] [ 1/2 gooey ] unit-test
-[ object ] [ object object class/\ ] unit-test
-[ fixnum ] [ fixnum object class/\ ] unit-test
-[ fixnum ] [ object fixnum class/\ ] unit-test
-[ fixnum ] [ fixnum fixnum class/\ ] unit-test
-[ fixnum ] [ fixnum integer class/\ ] unit-test
-[ fixnum ] [ integer fixnum class/\ ] unit-test
-[ vector fixnum class/\ ] unit-test-fails
-[ integer ] [ fixnum bignum class\/ ] unit-test
-[ integer ] [ fixnum integer class\/ ] unit-test
-[ rational ] [ ratio integer class\/ ] unit-test
+[ object ] [ object object class-and ] unit-test
+[ fixnum ] [ fixnum object class-and ] unit-test
+[ fixnum ] [ object fixnum class-and ] unit-test
+[ fixnum ] [ fixnum fixnum class-and ] unit-test
+[ fixnum ] [ fixnum integer class-and ] unit-test
+[ fixnum ] [ integer fixnum class-and ] unit-test
+[ vector fixnum class-and ] unit-test-fails
+[ integer ] [ fixnum bignum class-or ] unit-test
+[ integer ] [ fixnum integer class-or ] unit-test
+[ rational ] [ ratio integer class-or ] unit-test
5 f <literal> 6 f <literal> unify-results value-class
] unit-test
-[ [ 0 | 2 ] ] [ [ 2 "Hello" ] infer ] unit-test
-[ [ 1 | 2 ] ] [ [ dup ] infer ] unit-test
+[ [ 0 | 2 ] ] [ [ 2 "Hello" ] infer old-effect ] unit-test
+[ [ 1 | 2 ] ] [ [ dup ] infer old-effect ] unit-test
-[ [ 1 | 2 ] ] [ [ [ dup ] call ] infer ] unit-test
-[ [ call ] infer ] unit-test-fails
+[ [ 1 | 2 ] ] [ [ [ dup ] call ] infer old-effect ] unit-test
+[ [ call ] infer old-effect ] unit-test-fails
-[ [ 2 | 4 ] ] [ [ 2dup ] infer ] unit-test
-[ [ 2 | 0 ] ] [ [ set-vector-length ] infer ] unit-test
-[ [ 2 | 0 ] ] [ [ vector-push ] infer ] unit-test
+[ [ 2 | 4 ] ] [ [ 2dup ] infer old-effect ] unit-test
+[ [ 2 | 0 ] ] [ [ set-vector-length ] infer old-effect ] unit-test
+[ [ 2 | 0 ] ] [ [ vector-push ] infer old-effect ] unit-test
-[ [ 1 | 0 ] ] [ [ [ ] [ ] ifte ] infer ] unit-test
-[ [ ifte ] infer ] unit-test-fails
-[ [ [ ] ifte ] infer ] unit-test-fails
-[ [ [ 2 ] [ ] ifte ] infer ] unit-test-fails
-[ [ 4 | 3 ] ] [ [ [ rot ] [ -rot ] ifte ] infer ] unit-test
+[ [ 1 | 0 ] ] [ [ [ ] [ ] ifte ] infer old-effect ] unit-test
+[ [ ifte ] infer old-effect ] unit-test-fails
+[ [ [ ] ifte ] infer old-effect ] unit-test-fails
+[ [ [ 2 ] [ ] ifte ] infer old-effect ] unit-test-fails
+[ [ 4 | 3 ] ] [ [ [ rot ] [ -rot ] ifte ] infer old-effect ] unit-test
[ [ 4 | 3 ] ] [
[
] [
-rot
] ifte
- ] infer
+ ] infer old-effect
] unit-test
-[ [ 1 | 1 ] ] [ [ dup [ ] when ] infer ] unit-test
-[ [ 1 | 1 ] ] [ [ dup [ dup fixnum* ] when ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ [ dup fixnum* ] when ] infer ] unit-test
+[ [ 1 | 1 ] ] [ [ dup [ ] when ] infer old-effect ] unit-test
+[ [ 1 | 1 ] ] [ [ dup [ dup fixnum* ] when ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ [ dup fixnum* ] when ] infer old-effect ] unit-test
-[ [ 1 | 0 ] ] [ [ [ drop ] when* ] infer ] unit-test
-[ [ 1 | 1 ] ] [ [ [ { { [ ] } } ] unless* ] infer ] unit-test
+[ [ 1 | 0 ] ] [ [ [ drop ] when* ] infer old-effect ] unit-test
+[ [ 1 | 1 ] ] [ [ [ { { [ ] } } ] unless* ] infer old-effect ] unit-test
[ [ 0 | 1 ] ] [
- [ [ 2 2 fixnum+ ] dup [ ] when call ] infer
+ [ [ 2 2 fixnum+ ] dup [ ] when call ] infer old-effect
] unit-test
[
: infinite-loop infinite-loop ;
-[ [ infinite-loop ] infer ] unit-test-fails
+[ [ infinite-loop ] infer old-effect ] unit-test-fails
: simple-recursion-1
dup [ simple-recursion-1 ] [ ] ifte ;
-[ [ 1 | 1 ] ] [ [ simple-recursion-1 ] infer ] unit-test
+[ [ 1 | 1 ] ] [ [ simple-recursion-1 ] infer old-effect ] unit-test
: simple-recursion-2
dup [ ] [ simple-recursion-2 ] ifte ;
-[ [ 1 | 1 ] ] [ [ simple-recursion-2 ] infer ] unit-test
+[ [ 1 | 1 ] ] [ [ simple-recursion-2 ] infer old-effect ] unit-test
: bad-recursion-1
dup [ drop bad-recursion-1 5 ] [ ] ifte ;
-[ [ bad-recursion-1 ] infer ] unit-test-fails
+[ [ bad-recursion-1 ] infer old-effect ] unit-test-fails
: bad-recursion-2
dup [ uncons bad-recursion-2 ] [ ] ifte ;
-[ [ bad-recursion-2 ] infer ] unit-test-fails
+[ [ bad-recursion-2 ] infer old-effect ] unit-test-fails
! Simple combinators
-[ [ 1 | 2 ] ] [ [ [ car ] keep cdr ] infer ] unit-test
+[ [ 1 | 2 ] ] [ [ [ car ] keep cdr ] infer old-effect ] unit-test
! Mutual recursion
DEFER: foe
! This form should not have a stack effect
: bad-bin 5 [ 5 bad-bin bad-bin 5 ] [ 2drop ] ifte ;
-[ [ bad-bin ] infer ] unit-test-fails
+[ [ bad-bin ] infer old-effect ] unit-test-fails
: nested-when ( -- )
t [
] when
] when ;
-[ [ 0 | 0 ] ] [ [ nested-when ] infer ] unit-test
+[ [ 0 | 0 ] ] [ [ nested-when ] infer old-effect ] unit-test
: nested-when* ( -- )
[
] when*
] when* ;
-[ [ 1 | 0 ] ] [ [ nested-when* ] infer ] unit-test
+[ [ 1 | 0 ] ] [ [ nested-when* ] infer old-effect ] unit-test
SYMBOL: sym-test
-[ [ 0 | 1 ] ] [ [ sym-test ] infer ] unit-test
-
-[ [ 2 | 1 ] ] [ [ fie ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ foe ] infer ] unit-test
-
-[ [ 2 | 1 ] ] [ [ 2list ] infer ] unit-test
-[ [ 3 | 1 ] ] [ [ 3list ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ append ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ swons ] infer ] unit-test
-[ [ 1 | 2 ] ] [ [ uncons ] infer ] unit-test
-[ [ 1 | 1 ] ] [ [ unit ] infer ] unit-test
-[ [ 1 | 2 ] ] [ [ unswons ] infer ] unit-test
-! [ [ 1 | 1 ] ] [ [ last* ] infer ] unit-test
-! [ [ 1 | 1 ] ] [ [ last ] infer ] unit-test
-! [ [ 1 | 1 ] ] [ [ list? ] infer ] unit-test
-
-[ [ 1 | 1 ] ] [ [ length ] infer ] unit-test
-[ [ 1 | 1 ] ] [ [ reverse ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ contains? ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ tree-contains? ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ remove ] infer ] unit-test
-! [ [ 1 | 1 ] ] [ [ prune ] infer ] unit-test
-
-[ [ 2 | 1 ] ] [ [ bitor ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ bitand ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ bitxor ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ mod ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ /i ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ /f ] infer ] unit-test
-[ [ 2 | 2 ] ] [ [ /mod ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ + ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ - ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ * ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ / ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ < ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ <= ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ > ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ >= ] infer ] unit-test
-[ [ 2 | 1 ] ] [ [ number= ] infer ] unit-test
-
-[ [ 2 | 1 ] ] [ [ = ] infer ] unit-test
-
-[ [ 1 | 0 ] ] [ [ >n ] infer ] unit-test
-[ [ 0 | 1 ] ] [ [ n> ] infer ] unit-test
-
-[ [ 1 | 1 ] ] [ [ get ] infer ] unit-test
-
-! Type inference.
-
-[ [ [ object ] [ ] ] ] [ [ drop ] type-infer ] unit-test
-[ [ [ object ] [ object object ] ] ] [ [ dup ] type-infer ] unit-test
-[ [ [ object object ] [ cons ] ] ] [ [ cons ] type-infer ] unit-test
-[ [ [ cons ] [ cons ] ] ] [ [ uncons cons ] type-infer ] unit-test
+[ [ 0 | 1 ] ] [ [ sym-test ] infer old-effect ] unit-test
+
+[ [ 2 | 1 ] ] [ [ fie ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ foe ] infer old-effect ] unit-test
+
+[ [ 2 | 1 ] ] [ [ 2list ] infer old-effect ] unit-test
+[ [ 3 | 1 ] ] [ [ 3list ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ append ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ swons ] infer old-effect ] unit-test
+[ [ 1 | 2 ] ] [ [ uncons ] infer old-effect ] unit-test
+[ [ 1 | 1 ] ] [ [ unit ] infer old-effect ] unit-test
+[ [ 1 | 2 ] ] [ [ unswons ] infer old-effect ] unit-test
+! [ [ 1 | 1 ] ] [ [ last* ] infer old-effect ] unit-test
+! [ [ 1 | 1 ] ] [ [ last ] infer old-effect ] unit-test
+! [ [ 1 | 1 ] ] [ [ list? ] infer old-effect ] unit-test
+
+[ [ 1 | 1 ] ] [ [ length ] infer old-effect ] unit-test
+[ [ 1 | 1 ] ] [ [ reverse ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ contains? ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ tree-contains? ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ remove ] infer old-effect ] unit-test
+! [ [ 1 | 1 ] ] [ [ prune ] infer old-effect ] unit-test
+
+[ [ 2 | 1 ] ] [ [ bitor ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ bitand ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ bitxor ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ mod ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ /i ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ /f ] infer old-effect ] unit-test
+[ [ 2 | 2 ] ] [ [ /mod ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ + ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ - ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ * ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ / ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ < ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ <= ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ > ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ >= ] infer old-effect ] unit-test
+[ [ 2 | 1 ] ] [ [ number= ] infer old-effect ] unit-test
+
+[ [ 2 | 1 ] ] [ [ = ] infer old-effect ] unit-test
+
+[ [ 1 | 0 ] ] [ [ >n ] infer old-effect ] unit-test
+[ [ 0 | 1 ] ] [ [ n> ] infer old-effect ] unit-test
+
+[ [ 1 | 1 ] ] [ [ get ] infer old-effect ] unit-test
+
+! Type inference
+
+[ [ [ object ] [ ] ] ] [ [ drop ] infer ] unit-test
+[ [ [ object ] [ object object ] ] ] [ [ dup ] infer ] unit-test
+[ [ [ object object ] [ cons ] ] ] [ [ cons ] infer ] unit-test
+[ [ [ cons ] [ cons ] ] ] [ [ uncons cons ] infer ] unit-test
CELL index = to_fixnum(dpop());
if(index < 0 || index >= sbuf->top)
- range_error(tag_object(sbuf),0,to_fixnum(index),sbuf->top);
+ range_error(tag_object(sbuf),0,tag_fixnum(index),sbuf->top);
dpush(string_nth(untag_string(sbuf->string),index));
}
void set_sbuf_nth(F_SBUF* sbuf, CELL index, uint16_t value)
{
if(index < 0)
- range_error(tag_object(sbuf),0,to_fixnum(index),sbuf->top);
+ range_error(tag_object(sbuf),0,tag_fixnum(index),sbuf->top);
else if(index >= sbuf->top)
sbuf_ensure_capacity(sbuf,index + 1);
CELL index = to_fixnum(dpop());
if(index < 0 || index >= string->capacity)
- range_error(tag_object(string),0,to_fixnum(index),string->capacity);
+ range_error(tag_object(string),0,tag_fixnum(index),string->capacity);
dpush(tag_fixnum(string_nth(string,index)));
}
index = to_fixnum(dpop());
if(index < 0 || index > string->capacity)
{
- range_error(tag_object(string),0,to_fixnum(index),string->capacity);
+ range_error(tag_object(string),0,tag_fixnum(index),string->capacity);
result = -1; /* can't happen */
}
else if(TAG(ch) == FIXNUM_TYPE)
array = untag_array(vector->array);
if(length < 0)
- range_error(tag_object(vector),0,to_fixnum(length),vector->top);
+ range_error(tag_object(vector),0,tag_fixnum(length),vector->top);
vector->top = length;
if(length > array->capacity)
vector->array = tag_object(grow_array(array,length,F));
CELL index = to_fixnum(dpop());
if(index < 0 || index >= vector->top)
- range_error(tag_object(vector),0,to_fixnum(index),vector->top);
+ range_error(tag_object(vector),0,tag_fixnum(index),vector->top);
dpush(array_nth(untag_array(vector->array),index));
}
value = dpop();
if(index < 0)
- range_error(tag_object(vector),0,to_fixnum(index),vector->top);
+ range_error(tag_object(vector),0,tag_fixnum(index),vector->top);
else if(index >= vector->top)
vector_ensure_capacity(vector,index);