Created
April 7, 2018 00:25
-
-
Save greggirwin/9e6dc837daa7218faee81b81c57f520f to your computer and use it in GitHub Desktop.
Old R2 MAKE dialect experiment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REBOL [] | |
do %rmake.r | |
change-dir %./test-files/ | |
spec-1: [ | |
target %xxx.bld | |
depends on [%xxx-0.txt %xxx-1.txt] | |
made by [ | |
print ["rebuilding" _target "from" _source] | |
;print mold _spec/:_target/sources | |
write _target rejoin [now/time/precise newline read _source] | |
] | |
target %xxx-1.txt | |
depends on %xxx-2.txt | |
made by [ | |
print ["rebuilding" _target "from" _source] | |
write _target rejoin [_target tab now/time/precise newline read _source] | |
] | |
target %xxx-2.txt | |
depends on %xxx-3.txt | |
made by [ | |
print ["rebuilding" _target "from" _source] | |
;print mold _spec/:_target/sources | |
write _target rejoin [_target tab now/time/precise newline read _source] | |
] | |
] | |
;res: rmake/build-spec spec-1 | |
;print mold res | |
rmake/build spec-1 ;res | |
;rmake/build/part res %xxx.bld | |
;rmake/build/part res %xxx-2.txt | |
;------------------------------------------------------------- | |
; make-doc-pro launcher | |
mdp: %make-doc-pro.r | |
;secure [net allow file [allow read allow write ask execute]] | |
run-mdp: [ | |
print ["rebuilding" _target "from" _source] | |
do/args mdp get-modes _source 'full-path | |
] | |
; I'm not sure if I like having to compose and reduce things to use | |
; external blocks, but that's what I had to do here for now. Look at | |
; the first target below for an example. | |
mdp-spec: compose [ | |
target %mdp-test.html | |
depends on %mdp-test.txt | |
made by (reduce [run-mdp]) | |
target %mdp-test2.html | |
depends on %mdp-test2.txt | |
made by [ | |
print ["rebuilding" _target "from" _source] | |
do/args mdp get-modes _source 'full-path | |
] | |
] | |
;res: rmake/build-spec mdp-spec | |
;print mold res | |
;rmake/build mdp-spec ;res | |
;rmake/build/part mdp-spec %mdp-test2.html | |
;rmake/build/part mdp-spec [%mdp-test.html %mdp-test2.html] | |
mdp-spec: compose [ | |
target %mdp-test.html depends on %mdp-test.txt made by (reduce [run-mdp]) | |
target %mdp-test2.html depends on %mdp-test2.txt made by (reduce [run-mdp]) | |
] | |
rmake/build/all-targets mdp-spec | |
change-dir %.. | |
halt | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REBOL [ | |
Title: "rmake" | |
File: %rmake.r | |
Author: "Gregg Irwin" | |
EMail: [email protected] | |
Version: 0.0.4 | |
Copyright: "Copyright © 2002 Pointillistic Software. All Rights Reserved." | |
history: [ | |
0.0.1 [ | |
{Initial test version. Handles at least a couple simple test cases.} | |
] | |
0.0.2 [ | |
{Added some more smarts and the _spec, _target, and _source words | |
for accessing what's currently being processed.} | |
] | |
0.0.3 [ | |
{BUILD now takes a spec directly so you don't have to build it with | |
build-spec first. It will do that for you. If you pre-build your | |
spec, use the /no-parse refinement to tell BUILD not to parse it.} | |
] | |
0.0.4 [ | |
{Changed storage for object level vars in recursive call. | |
It uses a stack now.} | |
] | |
] | |
comment: { | |
'_spec, '_target, and '_source can be used in your actions to refer to | |
the current spec, target, and source being processed. | |
} | |
] | |
pull: func [ | |
"Remove and return items from a series." | |
series [series! none!] | |
/tail "Pull items from the tail end" | |
/part "The number of items to pull; one is the default" | |
range [number!] | |
/local result | |
] [ | |
if none? series [return none] | |
if tail [series: skip system/words/tail series negate any [range 1]] | |
result: either part [copy/part series range] [pick series 1] | |
either part [remove/part series range][remove series] | |
result | |
] | |
rmake: make object! [ | |
; Current spec, target, and source in BUILD function. These are here so | |
; you can reference them in your rules. | |
_spec: | |
_target: ; $@ $$@ | |
_source: ; $< | |
none | |
; Working vars for dialect parser | |
spec: copy [] | |
target: sources: actions: none | |
; used during nested calls | |
stack: copy [] | |
frame: [_target _source] | |
push: does [dent-in repend stack frame] | |
pop: does [dent-out set frame pull/tail/part stack length? frame] | |
newer?: func [ | |
{Returns true if target-1 was modified more recently than target-2; | |
false otherwise.} | |
target-1 [file! url!] | |
target-2 [file! url!] | |
][ | |
if not exists? target-1 [return false] | |
either any [ | |
all [(not none? modified? target-1) (none? modified? target-2)] | |
(greater? modified? target-1 modified? target-2) | |
] [true] [false] | |
] | |
dent-in: does [insert dump-dent #"^-"] | |
dent-out: does [remove dump-dent] | |
dump-dent: copy "" | |
show-trace: func [val] [ | |
print [dump-dent reduce val] | |
] | |
;== START PARSE RULES ================================== | |
action-rule: ['made 'by set actions [word! | block!]] | |
source-rule: ['depends 'on set sources [file! | block!]] | |
; If we wanted to allow, like MAKE, the ability to add dependencies | |
; to a task in multiple places, I think we should only need to alter | |
; this to find the existing target in the spec and add to it, rather | |
; than adding it as a new target. | |
target-rule: [ | |
'target set target [word! | file!] source-rule action-rule ( | |
append spec target | |
; The COMPOSE with brackets here forces sources and actions | |
; to become blocks so we can always FOREACH or DO them. | |
append/only spec compose/deep [sources [(sources)] actions [(actions)]] | |
sources: actions: none | |
) | |
] | |
;-- This is the top level rule. | |
make-rule: [some target-rule] | |
;== END PARSE RULES ================================== | |
;-- Build a dependency/action table and return it. Note that there is no | |
; reason you can't just define the table yourself. Using the dialect may | |
; be better for documentation, and certainly better for non-programmers, | |
; though it is a little more verbose. | |
build-spec: func [ | |
{Build a dependency spec from a MAKE dialect spec.} | |
make-spec [block!] "The spec for the table, given in the rmake dialect" | |
][ | |
clear spec | |
target: sources: actions: none | |
parse make-spec make-rule | |
return spec | |
] | |
; This uses a depth-first, recursive approach. It does not track | |
; visited nodes or do anything particularly smart like a real | |
; topological sort. | |
build: func [ | |
{Builds the target, using the make-spec as its dependency guide. | |
If no target is given, the first one in the spec is used.} | |
make-spec {Spec containing dependencies. Most likely this will | |
have been built by the build-spec function.} | |
/part {Build just the specified target(s).} | |
targets [file! block!] | |
/all-targets {Force a build of all targets in spec.} | |
/no-parse {Don't parse make-spec. It's preformatted, either by | |
being run through build-spec or by hand.} | |
/trace | |
][ | |
_spec: either no-parse [make-spec] [build-spec make-spec] | |
;print ["***" mold _spec] | |
if all-targets [targets: extract _spec 2] | |
if all [(not all-targets) (not part)] [ | |
;print ["&&&" mold make-spec] | |
targets: first _spec | |
] | |
;print ["%%%" mold _spec] | |
targets: compose [(targets)] | |
;print ["build" mold targets] | |
foreach target targets [ | |
_target: target | |
if trace [show-trace ['TARGET: _target]] | |
;print mold find/skip _spec target 2 | |
either find/skip _spec target 2 [ | |
; Pass 1: Check to see if any sources need to be built. | |
foreach source _spec/:target/sources [ | |
_source: source | |
; Check each source to see if it's also a target that might | |
; need to be rebuilt. | |
if find/skip _spec source 2 [ | |
; This is a recursive call. We have to store and | |
; reset our object level vars; the recursive call | |
; changes them. Yeah, I know, make it properly | |
; reentrant. | |
push | |
either trace [ | |
build/no-parse/part/trace _spec source | |
][ | |
build/no-parse/part _spec source | |
] | |
pop | |
] | |
] | |
; Pass 2: Check to see if the original target now needs to be built. | |
;print [target _target mold _spec/:_target/sources] | |
foreach source _spec/:target/sources [ | |
_source: source | |
if trace [show-trace ['CHECK 'source: _source 'target: _target mold what-dir]] | |
if newer? source target [ | |
if trace [show-trace ['ACTION 'source: _source 'target: _target mold what-dir]] | |
;print [tab "do" mold make-spec/:_target/actions] | |
do bind/copy _spec/:_target/actions 'self | |
if trace [show-trace ['ACTION-COMPLETE]] | |
break ; only need to build it once. | |
] | |
] | |
][ | |
print ["Target" mold _target "doesn't exist in spec" mold _spec] | |
] | |
] | |
] | |
] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment