Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[java] port changes from dotnet/ in PAST::Op compilation

  • Loading branch information...
commit efcb917e2bbd7f0ff6f16a5a7a8e92d79c44410d 1 parent 7681c75
@mberends mberends authored
Showing with 101 additions and 71 deletions.
  1. +12 −13 java/compiler/Makefile
  2. +89 −58 java/compiler/PAST2JSTCompiler.pm
View
25 java/compiler/Makefile
@@ -1,13 +1,15 @@
# This works if you have parrot, parrot-nqp and javac in your path.
-CLASSES = classes/
+CLASSES_DIR = classes/
-JAVAC = javac -d $(CLASSES)
+JAVAC = javac -d $(CLASSES_DIR)
-all: $(CLASSES) gen_actions.pir gen_grammar.pir gen_jst.pir gen_past2jst.pir gen_jst2java.pir NQPSetting.jar
+# TODO add P6Objects.jar
+all: $(CLASSES_DIR) gen_actions.pir gen_grammar.pir gen_jst.pir \
+ gen_past2jst.pir gen_jst2java.pir NQPSetting.jar
-$(CLASSES):
- perl -MExtUtils::Command -e mkpath $(CLASSES)
+$(CLASSES_DIR):
+ perl -MExtUtils::Command -e mkpath $(CLASSES_DIR)
gen_actions.pir: Actions.pm
parrot-nqp --target=pir Actions.pm > gen_actions.pir
@@ -28,18 +30,15 @@ gen_jst2java.pir: JST2Java.pm
parrot-nqp --target=pir JST2Java.pm > gen_jst2java.pir
NQPSetting.java: NQPSetting.pm \
- gen_actions.pir \
- gen_grammar.pir \
- gen_jst.pir \
- gen_past2jst.pir \
- gen_jst2java.pir
+ compile.pir gen_actions.pir gen_grammar.pir gen_nqpoptimizer.pir gen_jst.pir gen_past2jst.pir gen_jst2java.pir
parrot compile.pir NQPSetting.pm --setting > NQPSetting.java
NQPSetting.jar: NQPSetting.java
$(JAVAC) -classpath ../runtime/RakudoRuntime.jar NQPSetting.java
- jar cf NQPSetting.jar -C $(CLASSES) .
+ jar cf NQPSetting.jar -C $(CLASSES_DIR) .
-P6Objects.java: compile.pir gen_actions.pir gen_grammar.pir gen_nqpoptimizer.pir gen_jst.pir gen_past2jst.pir gen_jst2java.pir ../../common/NQP/P6Objects.pm NQPSetting.jar
+P6Objects.java: ../../common/NQP/P6Objects.pm NQPSetting.jar \
+ compile.pir gen_actions.pir gen_grammar.pir gen_nqpoptimizer.pir gen_jst.pir gen_past2jst.pir gen_jst2java.pir
parrot compile.pir ../../common/NQP/P6Objects.pm --no-core-libs > P6Objects.java
P6Objects.jar: P6Objects.java
@@ -54,7 +53,7 @@ test-unixy: all
clean:
perl -MExtUtils::Command -e rm_f gen_*.pir *.class *.jar *.java
- perl -MExtUtils::Command -e rm_rf $(CLASSES)
+ perl -MExtUtils::Command -e rm_rf $(CLASSES_DIR)
# Java source code files "depend" on files in the dotnet/* directories,
# in the sense that they were manually translated.
View
147 java/compiler/PAST2JSTCompiler.pm
@@ -676,49 +676,68 @@ our multi sub jst_for(PAST::Op $op) {
}
elsif $op.pasttype eq 'if' {
- my $result := JST::If.new(
- JST::MethodCall.new(
- :on('Ops'), :name('unbox_int'), :type('int'), 'TC',
+ my $cond_evaluated := JST::Local.new( :name(get_unique_id('if_cond')) );
+ return JST::Stmts.new(
+ JST::Local.new(
+ :name($cond_evaluated.name), :isdecl(1), :type('RakudoObject'),
jst_for(PAST::Op.new(
:pasttype('callmethod'), :name('Bool'),
(@($op))[0]
))
),
- jst_for((@($op))[1])
+ JST::If.new(
+ unbox('int', $cond_evaluated),
+ jst_for((@($op))[1]),
+ (+@($op) == 3 ?? jst_for((@($op))[2]) !! $cond_evaluated)
+ )
);
- if +@($op) == 3 {
- $result.push(jst_for((@($op))[2]));
- }
- return $result;
}
elsif $op.pasttype eq 'unless' {
- my $result := JST::If.new(
- JST::MethodCall.new(
- :on('Ops'), :name('unbox_int'), :type('int'), 'TC',
+ my $cond_evaluated := get_unique_id('unless_cond');
+ my $temp;
+ return JST::Stmts.new(
+ ($temp := JST::Local.new(
+ :name(get_unique_id('unless_result')), :isdecl(1), :type('RakudoObject'), val(0)
+ )),
+ JST::Local.new(
+ :name($cond_evaluated), :isdecl(1), :type('RakudoObject'),
jst_for(PAST::Op.new(
:pasttype('call'), :name('&prefix:<!>'),
- (@($op))[0]
+ JST::Bind.new(lit($temp.name), jst_for((@($op))[0]))
))
),
- jst_for((@($op))[1])
+ JST::If.new(
+ JST::MethodCall.new(
+ :on('Ops'), :name('unbox_int'), :type('int'),
+ TC(), $cond_evaluated
+ ),
+ JST::Bind.new(lit($temp.name), jst_for((@($op))[1])),
+ JST::Bind.new(lit($temp.name), jst_for($cond_evaluated)),
+ ),
+ lit($temp.name)
);
- return $result;
}
- elsif $op.pasttype eq 'while' {
+ elsif $op.pasttype eq 'while' || $op.pasttype eq 'until' {
# Need labels for start and end.
my $test_label := get_unique_id('while_lab');
my $end_label := get_unique_id('while_end_lab');
my $cond_result := get_unique_id('cond');
# Compile the condition.
- my $cond := JST::Local.new(
- :name($cond_result), :isdecl(1), :type('RakudoObject'),
- jst_for(PAST::Op.new(
+ my $cop := $op.pasttype eq 'until'
+ ?? PAST::Op.new(
+ :pasttype('call'), :name('&prefix:<!>'),
+ (@($op))[0]
+ )
+ !! PAST::Op.new(
:pasttype('callmethod'), :name('Bool'),
(@($op))[0]
- ))
+ );
+ my $cond := JST::Local.new(
+ :name($cond_result.name), :isdecl(1), :type('RakudoObject'),
+ jst_for($cop)
);
# Compile the body.
@@ -729,10 +748,7 @@ our multi sub jst_for(PAST::Op $op) {
JST::Label.new( :name($test_label) ),
$cond,
JST::If.new(
- JST::MethodCall.new(
- :on('Ops'), :name('unbox_int'), :type('int'),
- 'TC', $cond_result
- ),
+ unbox('int', $cond_result),
$body,
JST::Stmts.new(
$cond_result,
@@ -894,7 +910,7 @@ our multi sub jst_for(PAST::Val $val) {
unless $val.value<SBI> {
pir::die("Can't use PAST::Val for a block reference for an as-yet uncompiled block");
}
- return $val.value<SBI>;
+ return JST::Literal.new( :value($val.value<SBI>) );
}
# Look up the type to box to.
@@ -910,26 +926,39 @@ our multi sub jst_for(PAST::Val $val) {
}
elsif pir::isa($val.value, 'Float') {
$primitive := 'num';
- $type := 'NQPNum';
+ $type := 'NQPNum'; # TODO: DROP
}
else {
- pir::die("Can not detect type of value")
+ pir::die("PAST2JSTCompiler.pm cannot detect type of value")
}
- my $type_jst := emit_lexical_lookup($type);
- # Add to constants table.
+ # If we have a non-object type context, can hand back a literal value.
+ if $*TYPE_CONTEXT ne 'obj' {
+ return JST::Literal.new(
+ :value($val.value),
+ :type(vm_type_for($primitive)),
+ :escape($primitive eq 'str')
+ );
+ }
+
+
+ # Otherwise, need to box it. Add to constants table if possible.
+# my $make_const := box($primitive, DNST::Literal.new(
+# TODO :value($val.value), :escape($primitive eq 'str') ));
+ my $type_jst := emit_lexical_lookup($type); # TODO: DROP
my $make_const := JST::MethodCall.new(
:on('Ops'), :name('box_' ~ $primitive), :type('RakudoObject'),
'TC',
JST::Literal.new( :value($val.value), :escape($primitive eq 'str') ),
$type_jst
);
- if $*IN_LOADINIT {
+ if $*IN_LOADINIT || $*COMPILING_NQP_SETTING {
return $make_const;
}
else {
my $const_id := +@*CONSTANTS;
@*CONSTANTS.push($make_const);
+# TODO return DNST::Literal.new( :value("ConstantsTable[$const_id]") );
return "ConstantsTable[$const_id]";
}
}
@@ -1033,30 +1062,13 @@ our multi sub jst_for(PAST::Var $var) {
}
return $lookup;
-# if $var.isdecl { pir::die("PAST2JSTCompiler.pm does not know how to handle is_decl on package"); }
-
- # Get all parts of the name.
- # my @parts;
- # if $var.namespace {
- # for $var.namespace { @parts.push($_); }
- # }
- # @parts.push($var.name);
-
- # First, we need to look up the first part.
- # my $lookup := emit_lexical_lookup(@parts.shift);
-
- # Now chase down the rest.
- # for @parts {
- # # XXX todo: wrap the lookup in postcircumfix:<{ }> call(s).
- # pir::die('Multi-level package lookups NYI');
- # }
-
-# return $lookup;
}
elsif $scope eq 'register' {
if $var.isdecl {
my $result := JST::Local.new( :name($var.name), :isdecl(1), :type('RakudoObject') );
- unless $*BIND_CONTEXT { $result.push('null'); }
+ unless $*BIND_CONTEXT {
+ $result.push(ST::Null.new());
+ }
return $result;
}
elsif $*BIND_CONTEXT {
@@ -1077,14 +1089,28 @@ our multi sub jst_for(PAST::Var $var) {
}
# Emit attribute lookup/bind.
- return JST::MethodCall.new(
- :on('Ops'), :name($*BIND_CONTEXT ?? 'bind_attr' !! 'get_attr'),
- :type('RakudoObject'),
- 'TC',
+ my $lookup := emit_op(($*BIND_CONTEXT ?? 'bind_attr' !! 'get_attr'),
$self,
$class,
JST::Literal.new( :value($var.name), :escape(1) )
);
+ if $*BIND_CONTEXT {
+ $lookup.push($*BIND_VALUE);
+ }
+ elsif pir::defined($var.viviself) {
+ # May need to auto-vivify.
+ my $viv_name := get_unique_id('viv_attr_');
+ my $temp := JST::Local.new( :name($viv_name), :isdecl(1), :type('RakudoObject'), $lookup );
+ $lookup := JST::Stmts.new(
+ $temp,
+ JST::If.new( :bool(1),
+ eq(JST::Local.new( :name($viv_name) ), DNST::Null.new()),
+ jst_for($var.viviself),
+ JST::Local.new( :name($viv_name) )
+ )
+ );
+ }
+ return $lookup;
}
elsif $scope eq 'keyed_int' {
# XXX viviself, vivibase.
@@ -1134,13 +1160,13 @@ sub declare_lexical($var) {
# Run viviself if there is one and bind it.
if pir::defined($var.viviself) {
- my $*BIND_CONTEXT := 'bind_lex';
- my $result := emit_lexical_lookup($var.name);
+ my $*BIND_CONTEXT := 1;
+ my $*BIND_VALUE;
{
- my $*BIND_CONTEXT := '';
- $result.push(jst_for($var.viviself));
+ my $*BIND_CONTEXT := 0;
+ $*BIND_VALUE := jst_for($var.viviself);
}
- return $result;
+ return emit_lexical_lookup($var.name);
}
else {
return emit_lexical_lookup($var.name);
@@ -1162,6 +1188,11 @@ our multi sub jst_for($any) {
}
}
+# Non-regex nodes reached inside a regex
+our multi sub jst_regex($r) {
+ jst_for($r)
+}
+
# Emits a lookup of a lexical.
sub emit_lexical_lookup($name) {
# TODO:
Please sign in to comment.
Something went wrong with that request. Please try again.