! Copyright (C) 2017 Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: accessors arrays assocs combinators combinators.short-circuit combinators.smart constructors fry kernel lexer math math.parser modern namespaces sequences sets splitting strings ; IN: modern.compiler << INITIALIZED-SYMBOL: left-decorators [ HS{ } clone ] >> << : make-left-decorator ( string -- ) left-decorators get adjoin ; >> << SYNTAX: \LEFT-DECORATOR: scan-token make-left-decorator ; >> LEFT-DECORATOR: delimiter LEFT-DECORATOR: deprecated LEFT-DECORATOR: final LEFT-DECORATOR: flushable LEFT-DECORATOR: foldable LEFT-DECORATOR: inline LEFT-DECORATOR: recursive : left-decorator? ( obj -- ? ) left-decorators get in? ; << ! Initialize with : foo ( -- ) .. ; already INITIALIZED-SYMBOL: arities [ H{ } clone 2 "" pick set-at ] >> << : make-arity ( n string -- ) arities get set-at ; >> << SYNTAX: \ARITY: scan-token scan-token string>number swap make-arity ; >> ARITY: \ABOUT: 1 ARITY: \ALIAS: 2 ARITY: \ARITY: 2 ARITY: \B: 1 ARITY: \BUILTIN: 1 ARITY: \CONSTANT: 2 ARITY: \DEFER: 1 ARITY: \FORGET: 1 ARITY: \GENERIC#: 3 ARITY: \GENERIC: 2 ARITY: \LEFT-DECORATOR: 1 ARITY: \HOOK: 3 ARITY: \IN: 1 ARITY: \INSTANCE: 2 ARITY: \MAIN: 1 ARITY: \MATH: 1 ARITY: \MIXIN: 1 ARITY: \PRIMITIVE: 2 ARITY: \QUALIFIED-WITH: 2 ARITY: \QUALIFIED: 1 ARITY: \RENAME: 3 ARITY: \SINGLETON: 1 ARITY: \SLOT: 1 ARITY: \SOLUTION: 1 ARITY: \SYMBOL: 1 ARITY: \UNUSE: 1 ARITY: \USE: 1 ARITY: \MEMO: 2 ARITY: \: 2 ! ARITY: \USING: 0 : get-arity ( string -- n/f ) arities get at ; << INITIALIZED-SYMBOL: variable-arities [ H{ } clone ] >> << : make-variable-arity ( n string -- ) variable-arities get set-at ; >> << SYNTAX: \VARIABLE-ARITY: scan-token scan-token swap make-arity ; >> VARIABLE-ARITY: \EXCLUDE: 2 VARIABLE-ARITY: \FROM: 2 VARIABLE-ARITY: \INTERSECTION: 1 VARIABLE-ARITY: \PREDICATE: 3 VARIABLE-ARITY: \SYNTAX: 1 VARIABLE-ARITY: \TUPLE: 1 VARIABLE-ARITY: \UNION: 1 VARIABLE-ARITY: \WORD: 2 VARIABLE-ARITY: \ vocabulary-root ( uri path -- obj ) ; TUPLE: vocabulary name words main ; CONSTRUCTOR: vocabulary ( name -- obj ) H{ } clone >>words ; CONSTANT: core-root T{ vocabulary-root f "git@github.com:factor/factor" "core/" } CONSTANT: basis-root T{ vocabulary-root f "git@github.com:factor/factor" "basis/" } CONSTANT: extra-root T{ vocabulary-root f "git@github.com:factor/factor" "extra/" } : syntax-vocabulary ( -- vocabulary ) "syntax" ; TUPLE: word name effect quot ; : add-word ( word vocabulary -- ) [ dup name>> ] [ words>> ] bi* set-at ; : find-sections ( literals -- sections ) [ ?first section-open? ] filter ; DEFER: map-literals : map-literal ( obj quot: ( obj -- obj' ) -- obj ) over { [ array? ] [ ?first section-open? ] } 1&& [ [ first3 swap ] dip map-literals swap 3array ] [ call ] if ; inline recursive : map-literals ( seq quot: ( obj -- obj' ) -- seq' ) '[ _ map-literal ] map ; inline recursive DEFER: map-literals! : map-literal! ( obj quot: ( obj -- obj' ) -- obj ) over { [ array? ] [ ?first section-open? ] } 1&& [ [ call drop ] [ map-literals! ] 2bi ] [ call ] if ; inline recursive : map-literals! ( seq quot: ( obj -- obj' ) -- seq ) '[ _ map-literal! ] map! ; inline recursive TUPLE: lexed tokens ; TUPLE: comment < lexed payload ; CONSTRUCTOR: comment ( tokens payload -- obj ) ; TUPLE: escaped-identifier < lexed name ; CONSTRUCTOR: escaped-identifier ( tokens name -- obj ) ; TUPLE: escaped-object < lexed name payload ; CONSTRUCTOR: escaped-object ( tokens name payload -- obj ) ; TUPLE: section < lexed tag payload ; CONSTRUCTOR:
section ( tokens tag payload -- obj ) ; TUPLE: named-section < lexed tag name payload ; CONSTRUCTOR: named-section ( tokens tag name payload -- obj ) ; TUPLE: upper-colon < lexed tag payload ; CONSTRUCTOR: upper-colon ( tokens tag payload -- obj ) ; TUPLE: lower-colon < lexed tag payload ; CONSTRUCTOR: lower-colon ( tokens tag payload -- obj ) ; TUPLE: matched < lexed tag payload ; CONSTRUCTOR: matched ( tokens tag payload -- obj ) ; TUPLE: single-bracket < matched ; CONSTRUCTOR: single-bracket ( tokens tag payload -- obj ) ; TUPLE: double-bracket < matched ; CONSTRUCTOR: double-bracket ( tokens tag payload -- obj ) ; TUPLE: single-brace < matched ; CONSTRUCTOR: single-brace ( tokens tag payload -- obj ) ; TUPLE: double-brace < matched ; CONSTRUCTOR: double-brace ( tokens tag payload -- obj ) ; TUPLE: single-paren < matched ; CONSTRUCTOR: single-paren ( tokens tag payload -- obj ) ; TUPLE: double-paren < matched ; CONSTRUCTOR: double-paren ( tokens tag payload -- obj ) ; TUPLE: double-quote < matched ; CONSTRUCTOR: double-quote ( tokens tag payload -- obj ) ; TUPLE: identifier < lexed name ; CONSTRUCTOR: identifier ( tokens name -- obj ) ; ERROR: unknown-literal tokens ; DEFER: literal>tuple : literal>tuple* ( obj -- tuple ) { ! Comment has to be first { [ dup ?first "!" head? ] [ [ ] [ ?second >string ] bi ] } ! Must be before escaped-identifier so that ``\ foo`` works { [ dup ?first "\\" tail? ] [ [ ] [ ?first >string ] [ ?second ] tri ] } { [ dup ?first "\\" head? ] [ [ ] [ ?second >string ] bi ] } { [ dup ?first section-open? ] [ dup first ":" tail? [ { [ ] [ first "<" ?head drop ":" ?tail drop ] [ ?second ?first >string ] [ ?second dup length 0 > [ rest dup [ [ literal>tuple ] map ] when ] when ] } cleave ] [ [ ] [ first "<" ?head drop ] [ rest but-last ?first dup [ [ literal>tuple ] map ] when ] tri
] if ] } { [ dup { [ ?first ":" tail? ] [ ?first strict-upper? ] } 1&& ] [ ! : .. ; FOO: ; [ ] [ ?first ":" ?tail drop ] [ rest dup ?last ";" tail? [ but-last ] when ?first dup [ [ literal>tuple ] map ] when ] tri ] } { [ dup ?first ":" tail? ] [ ! foo: 123 [ ] [ ?first >string ] [ second literal>tuple ] tri ] } { [ dup ?first "\"" tail? ] [ [ ] [ ?first >string ] [ second >string ] tri ] } { [ dup ?first "[" tail? ] [ [ ] [ ?first "[" ?tail drop ] [ rest but-last ?first dup [ [ literal>tuple ] map ] when ] tri ] } { [ dup ?first "{" tail? ] [ [ ] [ ?first "{" ?tail drop ] [ rest but-last ?first dup [ [ literal>tuple ] map ] when ] tri ] } { [ dup ?first "(" tail? ] [ [ ] [ ?first "(" ?tail drop ] [ rest but-last ?first dup [ [ literal>tuple ] map ] when ] tri ] } { [ dup ?second "[" head? ] [ [ ] [ ?first ] [ 2 tail but-last ] tri ] } { [ dup ?second "{" head? ] [ [ ] [ ?first ] [ 2 tail but-last ] tri ] } { [ dup ?second "(" head? ] [ [ ] [ ?first ] [ 2 tail but-last ] tri ] } { [ dup array? ] [ [ literal>tuple ] map ] } [ unknown-literal ] } cond ; : literal>tuple ( obj -- tuple ) dup { [ slice? ] [ string? ] } 1|| [ [ ] [ >string ] bi ] [ literal>tuple* ] if ; : literals>tuples ( seq -- seq' ) [ literal>tuple ] map ; : vocab>tuples ( path -- seq ) vocab>literals literals>tuples ; : string>tuples ( string -- seq ) string>literals literals>tuples ; : literals>vocabulary ( literals -- vocabulary ) ; ![[ GENERIC: tuple>string ( obj -- string ) M: sequence tuple>string [ tuple>string ] map " " join ; M: upper-colon tuple>string [ { [ tag>> ": " ] [ payload>> [ tuple>string ] map " " join ] [ drop " ;" ] } cleave ] "" append-outputs-as ; M: identifier tuple>string name>> ; ]] TUPLE: compilation-unit ; GENERIC: tuple>identifiers ( obj -- obj' ) M: comment tuple>identifiers drop f ; M: identifier tuple>identifiers drop f ; M: lower-colon tuple>identifiers drop f ; M: escaped-object tuple>identifiers drop f ; M: double-quote tuple>identifiers drop f ; M: single-bracket tuple>identifiers drop f ; M: single-brace tuple>identifiers drop f ; M: single-paren tuple>identifiers drop f ; M: double-bracket tuple>identifiers drop f ; M: double-brace tuple>identifiers drop f ; M: double-paren tuple>identifiers drop f ; M: section tuple>identifiers payload>> [ tuple>identifiers ] map concat 1array ; M: named-section tuple>identifiers payload>> [ tuple>identifiers ] map concat 1array ; ERROR: upper-colon-identifer-expected obj ; ERROR: unknown-upper-colon upper-colon string ; M: upper-colon tuple>identifiers [ ] [ payload>> ] [ tag>> ] tri { ! { "" [ ?first name>> ] } ! { "TUPLE" [ ?first name>> ] } ! make the default one ?first { "USE" [ drop f ] } { "USING" [ drop f ] } { "IN" [ drop f ] } { "M" [ drop f ] } { "FROM" [ drop f ] } { "LIBRARY" [ drop f ] } { "INSTANCE" [ drop f ] } { "ARTICLE" [ drop f ] } ! TODO: Should be a word imo { "ABOUT" [ drop f ] } ! TODO: Should be a word imo { "ROMAN-OP" [ ?first name>> "roman" prepend 1array ] } { "TYPEDEF" [ ?second name>> 1array ] } { "FUNCTION" [ ?second name>> 1array ] } { "GL-FUNCTION" [ ?second name>> 1array ] } { "TUPLE" [ ?first name>> [ ] [ "?" append ] bi 2array ] } { "UNION" [ ?first name>> [ ] [ "?" append ] bi 2array ] } { "ERROR" [ ?first name>> [ ] [ "?" append ] bi 2array ] } { "BUILTIN" [ ?first name>> [ ] [ "?" append ] bi 2array ] } { "SINGLETON" [ ?first name>> [ ] [ "?" append ] bi 2array ] } { "SINGLETONS" [ [ name>> [ ] [ "?" append ] bi 2array ] map concat ] } { "MIXIN" [ ?first name>> [ ] [ "?" append ] bi 2array ] } { "PREDICATE" [ ?first name>> [ ] [ "?" append ] bi 2array ] } { "C-TYPE" [ ?first name>> [ ] [ "?" append ] bi 2array ] } { "SLOT" [ ?first name>> ">>" append 1array ] } [ drop ?first name>> 1array ] } case nip ; M: sequence tuple>identifiers [ tuple>identifiers ] map sift concat ; : vocab>identifiers ( vocab -- hashtable ) vocab>tuples tuple>identifiers ; : string>identifiers ( string -- identifiers ) string>tuples tuple>identifiers ; ![[ GENERIC: fixup-arity ( obj -- seq ) ERROR: closing-tag-required obj ; M: uppercase-colon-literal fixup-arity dup tag>> janky-arities ?at [ '[ _ swap [ any-comment? not ] cut-nth-match swap ] change-payload swap 2array dup first f >>closing-tag drop dup first [ ] [ underlying>> ] [ payload>> last-underlying-slice ] tri force-merge-slices >>underlying drop ! dup first " ;" >>closing-tag drop ] [ drop ! dup closing-tag>> [ B closing-tag-required ] unless ! dup closing-tag>> [ " ;" >>closing-tag ] unless ] if ; M: less-than-literal fixup-arity [ [ fixup-arity ] map ] change-payload ; M: object fixup-arity ; : postprocess-modern ( seq -- seq' ) collapse-decorators [ fixup-arity ] map flatten ; ]]