-
Notifications
You must be signed in to change notification settings - Fork 15
/
NieczaCompiler.pm6
97 lines (80 loc) · 2.88 KB
/
NieczaCompiler.pm6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class NieczaCompiler;
use JSYNC;
has $.module_finder;
has $.backend;
has $.stages;
has $.frontend;
has $.verbose;
has $.unitcache = {};
sub gettimeofday() { Q:CgOp { (rawscall Builtins,Kernel.GetNow) } }
method !compile($unitname, $filename, $modtime, $source, $main, $run, $end) {
my %*units;
my $*module_loader = sub ($m) { self!load_dependent($m) };
my $*verbose = $.verbose;
my $ast;
my @steps = (
$.frontend.typename => { $ast = $.frontend.parse(:$unitname,
:$filename, :$modtime, :$source); },
(map -> $st { $st.typename => { $ast = $st.invoke($ast) } }, @$.stages),
($.backend.typename ~ "-save") =>
{ $.backend.save_unit($unitname, $ast); $ast = Any },
($.backend.typename ~ "-post") =>
{ $.backend.post_save($unitname, :$main); },
($.backend.typename ~ "-run") =>
{ $run && $.backend.run($unitname); },
);
for @steps -> $step {
my $start = gettimeofday;
$step.value.();
my $time = gettimeofday() - $start;
if $.verbose {
say "$unitname: $step.key() took $time";
}
if $end eq $step.key {
say to-jsync($ast);
last;
}
}
}
method compile_module($module, $stop = "") {
my ($filename, $modtime, $source) = $.module_finder.load_module($module);
self!compile($module, $filename, $modtime, $source, False, False, $stop);
}
method compile_file($file, $run, $stop = "") {
my ($filename, $modtime, $source) = $.module_finder.load_file($file);
self!compile("MAIN", $filename, $modtime, $source, True, $run, $stop);
}
method compile_string($source, $run, $stop = "") {
self!compile("MAIN", "(eval)", 0, $source, True, $run, $stop);
}
method !up_to_date($mod) {
say "Checking datedness of $mod.name()" if $.verbose;
for $mod.tdeps.pairs -> $p {
my ($filename, $modtime, $source) = $.module_finder.load_module($p.key);
if $filename ne $p.value.[0] {
say "$p.key() resolves to $filename now, was $p.value.[0]" if $.verbose;
return False;
}
if $modtime > $p.value.[1] {
say "$p.key() mod-time increased from $p.value.[1] to $modtime" if $.verbose;
return False;
}
}
return True;
}
method !load_dependent($module) {
say "Trying to load depended module $module" if $.verbose;
my $newmod = $.unitcache{$module} //= $.backend.get_unit($module);
if !defined($newmod) || !self!up_to_date($newmod) {
$.unitcache{$module}:delete;
say "(Re)compilation needed" if $.verbose;
self.compile_module($module);
$newmod = $.unitcache{$module} = $.backend.get_unit($module);
}
%*units{$module} = $newmod;
for keys $newmod.tdeps -> $mn {
%*units{$mn} //= ($.unitcache{$mn} //= $.backend.get_unit($mn));
}
say "Loaded $module" if $.verbose;
$newmod;
}