Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Initial setting implementation.
  • Loading branch information
arnsholt committed Nov 29, 2014
1 parent c3ba195 commit 8d2700e
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 4 deletions.
10 changes: 8 additions & 2 deletions Makefile
Expand Up @@ -5,17 +5,23 @@ MOAR=$(PREFIX)/bin/moar
MOARS=blib/Snake/Actions.moarvm \
blib/Snake/Compiler.moarvm \
blib/Snake/Grammar.moarvm \
blib/Snake/Metamodel/ClassHOW.moarvm \
blib/Snake/ModuleLoader.moarvm \
blib/Snake/World.moarvm \
blib/Snake/Metamodel/ClassHOW.moarvm \
blib/snake.moarvm

.PHONY: all

all: $(MOARS)
all: $(MOARS) blib/SNAKE.setting.moarvm

blib/%.moarvm: src/%.nqp
$(NQP) --target=mbc --output=$@ $<

blib/SNAKE.setting.moarvm: src/setting/builtins.py $(MOARS)
./snake --setting=NULL --target=mbc --output=$@ $<

blib/Snake/Actions.moarvm: src/Snake/Actions.nqp blib/Snake/Metamodel/ClassHOW.moarvm
blib/Snake/Grammar.moarvm: src/Snake/Grammar.nqp blib/Snake/ModuleLoader.moarvm blib/Snake/World.moarvm

test: all
prove -r --exec ./snake t/sanity/*.t t/*.t
Expand Down
24 changes: 23 additions & 1 deletion src/Snake/Actions.nqp
Expand Up @@ -318,6 +318,8 @@ method suite:sym<normal>($/) {

method statement($/) { make $<stmt>.ast; }

method you_are_here($/) { make self.CTXSAVE() }

method stmt-list($/) {
if +$<simple-statement> > 1 {
my $stmts := QAST::Stmts.new();
Expand All @@ -337,9 +339,29 @@ method file-input($/) {
}
$*BLOCK.push: $stmts;

unless nqp::defined(%*COMPILING<%?OPTIONS><outer_ctx>) {
# We haven't got a specified outer context already, so load a
# setting.
my $SETTING := $*W.load_setting(%*COMPILING<%?OPTIONS><setting> // 'SNAKE');
}
self.SET_BLOCK_OUTER_CTX($*BLOCK);

# XXX: This has been cargo-culted from Rakudo. Should probably figure out
# how this API should be used (and what it can do).
make QAST::CompUnit.new($*BLOCK, :hll<snake>);
make QAST::CompUnit.new(
:hll<snake>,

:sc($*W.sc()),
:pre_deserialize($*W.load_dependency_tasks()),
:post_deserialize($*W.fixup_tasks()),

# TODO: These need to be different when we do modules and such
# properly.
:load(QAST::Op.new(:op<call>, QAST::BVal.new(:value($*BLOCK)))),
:main(QAST::Op.new(:op<call>, QAST::BVal.new(:value($*BLOCK)))),

$*BLOCK,
);
}

method line($/) { make $<statement>.ast if $<statement>; }
Expand Down
19 changes: 18 additions & 1 deletion src/Snake/Grammar.nqp
Expand Up @@ -3,6 +3,8 @@ use NQPHLL;
grammar Snake::Grammar is HLL::Grammar;

use Snake::Actions;
use Snake::ModuleLoader;
use Snake::World;

# Operator precedence levels, from tightest to loosest.
INIT {
Expand Down Expand Up @@ -38,6 +40,14 @@ method TOP() {
# I think).
my $*BLOCK := QAST::Block.new(QAST::Stmts.new(QAST::Var.new(:name<__args__>,
:scope<local>, :decl<param>, :slurpy(1))));
my $*UNIT := $*BLOCK;
my $file := nqp::getlexdyn('$?FILES');
my $source_id := nqp::sha1(self.target()) ~
(%*COMPILING<%?OPTIONS><stable-sc> ?? '' !! '-' ~ ~nqp::time_n());
my $*W := nqp::isnull($file) ??
Snake::World.new(:handle($source_id)) !!
Snake::World.new(:handle($source_id), :description($file));

# Default variables are assigned to block-scoped lexicals numbered
# sequentially. Naming derived from function definition and parameter name
# won't work if a block contains two defs for the same function with the
Expand Down Expand Up @@ -325,7 +335,14 @@ token suite:sym<normal> {
<.DEDENT>
}

token statement { $<stmt>=<stmt-list> <.NEWLINE> | $<stmt>=<compound-statement> }
token statement {
| <stmt=.stmt-list> <.NEWLINE>
| <stmt=.compound-statement>
| 'YOU_ARE_HERE' <.NEWLINE> <stmt=.you_are_here>
}

# Just a placeholder so the action gets called.
token you_are_here { <?> }

token stmt-list { <simple-statement>+ %% [<.ws> ';' <.ws>] }

Expand Down
57 changes: 57 additions & 0 deletions src/Snake/ModuleLoader.nqp
@@ -0,0 +1,57 @@
class Snake::ModuleLoader;

my $loaded_setting;

method search_path($file) {
my $path;
for ['.', 'blib'] -> $prefix {
if nqp::stat("$prefix/$file", 0) {
$path := "$prefix/$file";
last;
}
}
nqp::die("Unable to locate $file") if !$path;
$path
}

# Setting loading, how does it work?
# So this is slightly magical and mostly stolen from NQP, but as far as I grok
# it, this is the deal:
#
# 1) YOU_ARE_HERE creates the AST from Snake::Actions.CTXSAVE, which is
# inherited from HLL::Actions. This is a bit of code that looks up $*CTXSAVE,
# and if that object is able to .ctxsave(), calls that method on it.
#
# 2) The module loader sets $*CTXSAVE to itself, and loads the setting, which
# will call the code above as part of its mainline, triggering a call on
# .ctxsave(), where we save a reference to the context of the calling code,
# sc. the lexical environment we want code to run in.
method load_setting($name) {
my $setting;

if $name ne "NULL" {
unless $loaded_setting {
my $path := self.search_path("$name.setting.moarvm"); # XXX: Backend specific!
my $*CTXSAVE := self;
my $*MAIN_CTX := Snake::ModuleLoader;
nqp::loadbytecode($path);

if !nqp::defined($*MAIN_CTX) {
nqp::die("Couldn't load setting $name; maybe it's missing a YOU_ARE_HERE?");
}
$loaded_setting := $*MAIN_CTX;
}
$setting := $loaded_setting;
}

$setting;
}

method ctxsave() {
$*MAIN_CTX := nqp::ctxcaller(nqp::ctx());
$*CTXSAVE := 0;
}

nqp::bindhllsym('snake', 'ModuleLoader', Snake::ModuleLoader);

# vim: ft=perl6
37 changes: 37 additions & 0 deletions src/Snake/World.nqp
@@ -0,0 +1,37 @@
class Snake::World is HLL::World;

use Snake::ModuleLoader;

my $loader := nqp::gethllsym("snake", "ModuleLoader");

method load_setting($name) {
if $name ne "NULL" {
my $setting := $loader.load_setting($name);

my $set_outer := QAST::Op.new(:op<forceouterctx>,
QAST::BVal.new(:value($*UNIT)),
QAST::Op.new(:op<callmethod>, :name<load_setting>,
QAST::Op.new(:op<getcurhllsym>,
QAST::SVal.new(:value<ModuleLoader>)
),
QAST::SVal.new(:value($name)),
),
);
if self.is_precompilation_mode() {
# TODO
nqp::die("World.load_setting for precompilation NYI");
}
else {
self.add_load_dependency_task(:fixup_ast(
QAST::Op.new(:op<loadbytecode>,
QAST::SVal.new(:value<Snake/ModuleLoader.moarvm>)
)
));
self.add_fixup_task(:fixup_ast($set_outer));
}

nqp::ctxlexpad($setting);
}
}

# vim: ft=perl6
4 changes: 4 additions & 0 deletions src/setting/builtins.py
@@ -0,0 +1,4 @@
def print(msg):
nqp::say(msg)

YOU_ARE_HERE
3 changes: 3 additions & 0 deletions src/snake.nqp
Expand Up @@ -9,6 +9,9 @@ $comp.language('snake');
$comp.parsegrammar(Snake::Grammar);
$comp.parseactions(Snake::Actions);

my @options := $comp.commandline_options();
@options.push: 'setting=s';

sub MAIN(@args) {
$comp.command_line(@args, :encoding<utf8>);
}
Expand Down

0 comments on commit 8d2700e

Please sign in to comment.