#!/usr/bin/perl6
#
## Boolean type
#
class Sidef::Types::Bool::Bool {
has Bool $.value;
}
#
## String type + methods
#
class Sidef::Types::String::String {
has Str $.value;
method concat(Sidef::Types::String::String $arg) {
Sidef::Types::String::String.new(value => $.value ~ $arg.value);
}
method say() {
$.concat(Sidef::Types::String::String.new(value => "\n")).print;
}
method print() {
Sidef::Types::Bool::Bool.new(value => print $.value);
}
}
class Interpreter {
#
## Expression executor
#
method execute_expr($statement) {
defined($statement<self>) or die "Invalid AST!";
my $self_obj = $statement<self>;
if $self_obj.isa(Hash) {
$self_obj = $.execute($self_obj);
}
if defined($statement<call>) {
for @($statement<call>) -> $call {
my $meth = $call<method>;
if defined($call<arg>) {
my $args = $call<arg>.map({
$_.isa(Hash) ?? $.execute($_) !! $_
});
$self_obj = $self_obj."$meth"(|$args);
}
else {
$self_obj = $self_obj."$meth"();
}
}
}
return $self_obj;
}
#
## Parse-tree executor
#
method execute($structure) {
my $result;
defined($structure<main>) or die "Invalid AST!";
for @($structure<main>) -> $statement {
$result = $.execute_expr($statement);
}
return $result;
}
}
my $ast = {
main => [
{
self => {
main => [
{
self => {
main => [
{
call => [{ method => "print" }],
self => {
main => [
{
call => [
{
arg => [
{
main => [
{
self => {
main => [
{ self => Sidef::Types::String::String.bless(value => "llo") },
],
},
},
],
},
],
method => "concat",
},
],
self => Sidef::Types::String::String.bless(value => "He"),
},
],
},
},
],
},
},
],
},
},
{
self => {
main => [
{
self => {
main => [
{
call => [{ method => "say" }],
self => {
main => [
{ self => Sidef::Types::String::String.bless(value => " world!") },
],
},
},
],
},
},
],
},
},
],
};
#
## Begin execution
#
my $intr = Interpreter.new;
$intr.execute($ast);