Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eat own walk dogfood after #26 #547

Open
vendethiel opened this issue Aug 26, 2019 · 2 comments
Open

Eat own walk dogfood after #26 #547

vendethiel opened this issue Aug 26, 2019 · 2 comments

Comments

@vendethiel
Copy link
Collaborator

While we're still unsure of whether we want to write walk directly in Alma or first in Perl 6, these places would probably be good first customers:

alma/lib/Alma/Q.pm6

Lines 728 to 794 in a31aafc

sub interpolate($thing) {
return $thing.new(:elements($thing.elements.map(&interpolate)))
if $thing ~~ Val::Array;
return $thing.new(:properties(%($thing.properties.map({ .key => interpolate(.value) }))))
if $thing ~~ Val::Dict;
return $thing
if $thing ~~ Val;
if $thing ~~ Q::Term::Identifier {
if $runtime.lookup-frame-outside($thing, $quasi-frame) -> $frame {
return Q::Term::Identifier::Direct.new(:name($thing.name), :$frame);
}
else {
return $thing;
}
}
return $thing.new(:name($thing.name))
if $thing ~~ Q::Identifier;
if $thing ~~ Q::Unquote::Prefix {
my $prefix = $thing.expr.eval($runtime);
die X::TypeCheck.new(:operation("interpolating an unquote"), :got($prefix), :expected(Q::Prefix))
unless $prefix ~~ Q::Prefix;
return $prefix.new(:identifier($prefix.identifier), :operand($thing.operand));
}
elsif $thing ~~ Q::Unquote::Infix {
my $infix = $thing.expr.eval($runtime);
die X::TypeCheck.new(:operation("interpolating an unquote"), :got($infix), :expected(Q::Infix))
unless $infix ~~ Q::Infix;
return $infix.new(:identifier($infix.identifier), :lhs($thing.lhs), :rhs($thing.rhs));
}
if $thing ~~ Q::Unquote {
my $ast = $thing.expr.eval($runtime);
die "Expression inside unquote did not evaluate to a Q" # XXX: turn into X::
unless $ast ~~ Q;
return $ast;
}
if $thing ~~ Q::Term::My {
$runtime.declare-var($thing.identifier);
}
if $thing ~~ Q::Term::Func {
$runtime.enter($runtime.current-frame, Val::Dict.new, Q::StatementList.new);
for $thing.block.parameterlist.parameters.elements.map(*.identifier) -> $identifier {
$runtime.declare-var($identifier);
}
}
if $thing ~~ Q::Block {
$runtime.enter($runtime.current-frame, Val::Dict.new, $thing.statementlist);
}
my %attributes = $thing.attributes.map: -> $attr {
aname($attr) => interpolate(avalue($attr, $thing))
};
if $thing ~~ Q::Term::Func || $thing ~~ Q::Block {
$runtime.leave();
}
$thing.new(|%attributes);
}

alma/lib/Alma/Runtime.pm6

Lines 297 to 318 in a31aafc

sub interpolate($thing) {
return $thing.new(:elements($thing.elements.map(&interpolate)))
if $thing ~~ Val::Array;
return $thing.new(:properties(%($thing.properties.map(.key => interpolate(.value)))))
if $thing ~~ Val::Dict;
return $thing
if $thing ~~ Val;
return Q::Term::Identifier.new(:name($thing.name))
if $thing ~~ Q::Term::Identifier;
return $thing
if $thing ~~ Q::Unquote;
my %attributes = $thing.attributes.map: -> $attr {
aname($attr) => interpolate(avalue($attr, $thing))
};
$thing.new(|%attributes);
}

Seems like it would be more complex to reuse something written in Alma than in Perl 6, but would be an interesting assessment of "where are we now".

@masak
Copy link
Owner

masak commented Aug 27, 2019

Also this one:

sub check(Q $ast, $runtime) is export {
my %*assigned;
handle($ast);
# a bunch of nodes we don't care about descending into
multi handle(Q::ParameterList $) {}
multi handle(Q::Statement::Return $) {}
multi handle(Q::Statement::BEGIN $) {}
multi handle(Q::Literal $) {}
multi handle(Q::Term $) {} # with two exceptions, see below
multi handle(Q::Postfix $) {}
multi handle(Q::StatementList $statementlist) {
for $statementlist.statements.elements -> $statement {
handle($statement);
}
}
multi handle(Q::Statement::Block $block) {
$runtime.enter($runtime.current-frame, $block.block.static-lexpad, $block.block.statementlist);
handle($block.block.statementlist);
$block.block.static-lexpad = $runtime.current-frame.properties<pad>;
$runtime.leave();
}
multi handle(Q::Statement::Expr $expr) {
handle($expr.expr);
}
multi handle(Q::Statement::Func $func) {
my $outer-frame = $runtime.current-frame;
my $name = $func.identifier.name;
my $val = Val::Func.new(:$name,
:parameterlist($func.block.parameterlist),
:statementlist($func.block.statementlist),
:$outer-frame
);
$runtime.enter($outer-frame, Val::Dict.new, $func.block.statementlist, $val);
handle($func.block);
$runtime.leave();
$runtime.declare-var($func.identifier, $val);
}
multi handle(Q::Statement::Macro $macro) {
my $outer-frame = $runtime.current-frame;
my $name = $macro.identifier.name;
my $val = Val::Macro.new(:$name,
:parameterlist($macro.block.parameterlist),
:statementlist($macro.block.statementlist),
:$outer-frame
);
$runtime.enter($outer-frame, Val::Dict.new, $macro.block.statementlist, $val);
handle($macro.block);
$runtime.leave();
$runtime.declare-var($macro.identifier, $val);
}
multi handle(Q::Statement::If $if) {
handle($if.block);
}
multi handle(Q::Statement::For $for) {
handle($for.block);
}
multi handle(Q::Statement::While $while) {
handle($while.block);
}
multi handle(Q::Block $block) {
$runtime.enter($runtime.current-frame, Val::Dict.new, Q::StatementList.new);
handle($block.parameterlist);
handle($block.statementlist);
$block.static-lexpad = $runtime.current-frame.properties<pad>;
$runtime.leave();
}
multi handle(Q::Term::Dict $object) {
handle($object.propertylist);
}
multi handle(Q::Term::My $my) {
my $symbol = $my.identifier.name.value;
my $block = $runtime.current-frame();
die X::Redeclaration.new(:$symbol)
if $runtime.declared-locally($symbol);
die X::Redeclaration::Outer.new(:$symbol)
if %*assigned{$block ~ $symbol};
$runtime.declare-var($my.identifier);
}
multi handle(Q::PropertyList $propertylist) {
my %seen;
for $propertylist.properties.elements -> Q::Property $p {
my Str $property = $p.key.value;
die X::Property::Duplicate.new(:$property)
if %seen{$property}++;
}
}
multi handle(Q::Infix $infix) {
handle($infix.lhs);
handle($infix.rhs);
}
multi handle(Q::Expr::BlockAdapter $blockadapter) {
handle($blockadapter.block);
}
multi handle(Q::Postfix::Call $call) {
handle($call.operand);
for $call.argumentlist.arguments.elements.list -> $e {
handle($e);
}
}
multi handle(Q::Term::Func $func) {
handle($func.block);
}
multi handle(Q::Prefix $prefix) {
handle($prefix.operand);
}
}

@masak
Copy link
Owner

masak commented Sep 8, 2019

(And I guess that last one is a bit of an interesting outlier, since the previous two do whole-tree cloning, but this one only does traversal and side effects.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants