-
-
Notifications
You must be signed in to change notification settings - Fork 330
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit on reworking parser into generator nodes
- Loading branch information
1 parent
443adc1
commit e439800
Showing
8 changed files
with
606 additions
and
345 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require 'opal/nodes/base' | ||
require 'opal/nodes/literal' | ||
require 'opal/nodes/variables' | ||
require 'opal/nodes/constants' | ||
require 'opal/nodes/logic' | ||
require 'opal/nodes/definitions' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
module Opal | ||
class Parser | ||
class Node | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
adambeynon
Author
Contributor
|
||
def initialize(sexp, level, parser) | ||
@sexp = sexp | ||
@level = level | ||
@parser = parser | ||
end | ||
|
||
def type | ||
@sexp.type | ||
end | ||
|
||
def children | ||
@sexp[1..-1] | ||
end | ||
|
||
def compile_to_fragments | ||
return @fragments if @fragments | ||
|
||
@fragments = [] | ||
self.compile | ||
@fragments | ||
end | ||
|
||
def compile | ||
raise "Not Implemented" | ||
end | ||
|
||
def push(str) | ||
str = fragment(str) if str.is_a?(String) | ||
@fragments << str | ||
end | ||
|
||
def unshift(str) | ||
str = fragment(str) if str.is_a?(String) | ||
@fragments.unshift str | ||
end | ||
|
||
def wrap(pre, post) | ||
unshift pre | ||
push post | ||
end | ||
|
||
def fragment(str) | ||
Opal::Parser::Fragment.new str, @sexp | ||
end | ||
|
||
def scope | ||
@parser.scope | ||
end | ||
|
||
def s(*args) | ||
@parser.s(*args) | ||
end | ||
|
||
def expr(sexp) | ||
@parser.process sexp, :expr | ||
end | ||
|
||
def recv(sexp) | ||
@parser.process sexp, :recv | ||
end | ||
|
||
def stmt(sexp) | ||
@parser.process sexp, :stmt | ||
end | ||
|
||
def expr_or_nil(sexp) | ||
sexp ? expr(sexp) : "nil" | ||
end | ||
|
||
def reserved?(name) | ||
Opal::Parser::RESERVED.include? name | ||
end | ||
|
||
def property(name) | ||
reserved?(name) ? "['#{name}']" : ".#{name}" | ||
end | ||
|
||
def variable(name) | ||
reserved?(name) ? "#{name}$" : name | ||
end | ||
|
||
def add_local(name) | ||
scope.add_local name.to_sym | ||
end | ||
|
||
def add_ivar(name) | ||
scope.add_ivar name | ||
end | ||
|
||
def add_temp(temp) | ||
scope.add_temp temp | ||
end | ||
|
||
def helper(name) | ||
@parser.instance_variable_get(:@helpers)[name] = true | ||
end | ||
|
||
def with_temp(&block) | ||
@parser.with_temp(&block) | ||
end | ||
|
||
def in_while? | ||
@parser.in_while? | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
require 'opal/nodes/base' | ||
|
||
module Opal | ||
class Parser | ||
class ConstNode < Node | ||
def initialize(*) | ||
super | ||
@const_missing = true | ||
end | ||
|
||
def compile | ||
name = @sexp[1] | ||
|
||
if @const_missing | ||
with_temp do |tmp| | ||
push "((#{tmp} = $scope.#{name}) == null ? $opal.cm('#{name}') : #{tmp})" | ||
end | ||
else | ||
push "$scope.#{name}" | ||
end | ||
end | ||
end | ||
|
||
class CdeclNode < Node | ||
def compile | ||
push expr(@sexp[2]) | ||
wrap "$opal.cdecl($scope, '#{@sexp[1]}', ", ")" | ||
end | ||
end | ||
|
||
class CasgnNode < Node | ||
def compile | ||
push "$opal.casgn(" | ||
push expr(@sexp[1]) | ||
push ", '#{@sexp[2]}', " | ||
push expr(@sexp[3]) | ||
push ")" | ||
end | ||
end | ||
|
||
class Colon2Node < Node | ||
def initialize(*) | ||
super | ||
@const_missing = true | ||
end | ||
|
||
def lhs | ||
expr @sexp[1] | ||
end | ||
|
||
def compile | ||
if @const_missing | ||
with_temp do |tmp| | ||
push "((#{tmp} = (" | ||
push lhs | ||
push ")._scope).#{@sexp[2]} == null ? #{tmp}.cm('#{@sexp[2]}') : " | ||
push "#{tmp}.#{@sexp[2]})" | ||
end | ||
else | ||
push lhs | ||
wrap '(', ")._scope.#{@sexp[1]}" | ||
end | ||
end | ||
end | ||
|
||
class Colon3Node < Node | ||
def compile | ||
with_temp do |tmp| | ||
push "((#{tmp} = $opal.Object._scope.#{@sexp[1]}) == null ? " | ||
push "$opal.cm('#{@sexp[1]}') : #{tmp})" | ||
end | ||
end | ||
end | ||
|
||
class Casgn3Node < Node | ||
def compile | ||
push "$opal.casgn($opal.Object, '#{@sexp[1]}', " | ||
push expr(@sexp[2]) | ||
push ")" | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
require 'opal/nodes/base' | ||
|
||
module Opal | ||
class Parser | ||
|
||
class BaseScopeNode < Node | ||
def in_scope(type, &block) | ||
@parser.in_scope(type, &block) | ||
end | ||
end | ||
|
||
class SClassNode < BaseScopeNode | ||
def compile | ||
in_scope(:sclass) do | ||
add_temp '$scope = self._scope' | ||
add_temp 'def = self._proto' | ||
|
||
push scope.to_vars | ||
push stmt(@sexp[2]) | ||
end | ||
|
||
push "})(" | ||
push recv(@sexp[1]) | ||
wrap "(function(self) {", ".$singleton_class())" | ||
end | ||
end | ||
|
||
class UndefNode < Node | ||
# FIXME: we should be setting method to a stub method here | ||
def compile | ||
push "delete #{scope.proto}#{@parser.mid_to_jsid @sexp[1][1].to_s}" | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
require 'opal/nodes/base' | ||
|
||
module Opal | ||
class Parser | ||
class ValueNode < Node | ||
def compile | ||
push type.to_s | ||
end | ||
end | ||
|
||
class LiteralNode < Node | ||
def literal | ||
@sexp[1] | ||
end | ||
end | ||
|
||
class NumericNode < LiteralNode | ||
def compile | ||
push literal.to_s | ||
wrap '(', ')' if @level == :recv | ||
end | ||
end | ||
|
||
class StringNode < LiteralNode | ||
def compile | ||
push literal.inspect | ||
end | ||
end | ||
|
||
class SymbolNode < LiteralNode | ||
def compile | ||
push literal.to_s.inspect | ||
end | ||
end | ||
|
||
class RegexpNode < LiteralNode | ||
def compile | ||
push((literal == // ? /^/ : literal).inspect) | ||
end | ||
end | ||
|
||
class DynamicStringNode < Node | ||
def compile | ||
children.each_with_index do |part, idx| | ||
push " + " unless idx == 0 | ||
|
||
if String === part | ||
push part.inspect | ||
elsif part.type == :evstr | ||
push "(" | ||
push expr(part[1]) | ||
push ")" | ||
elsif part.type == :str | ||
push part[1].inspect | ||
else | ||
raise "Bad dstr part" | ||
end | ||
|
||
wrap '(', ')' if @level == :recv | ||
end | ||
end | ||
end | ||
|
||
class DynamicSymbolNode < Node | ||
def compile | ||
children.each_with_index do |part, idx| | ||
push " + " unless idx == 0 | ||
|
||
if String === part | ||
push part.inspect | ||
elsif part.type == :evstr | ||
push expr(s(:call, part.last, :to_s, s(:arglist))) | ||
elsif part.type == :str | ||
push part.last.inspect | ||
else | ||
raise "Bad dsym part" | ||
end | ||
end | ||
|
||
wrap '(', ')' | ||
end | ||
end | ||
|
||
class DynamicRegexpNode < Node | ||
def compile | ||
children.each_with_index do |part, idx| | ||
push " + " unless idx == 0 | ||
|
||
if String === part | ||
push part.inspect | ||
elsif part.type == :str | ||
push part[1].inspect | ||
else | ||
push expr(part[1]) | ||
end | ||
end | ||
|
||
wrap '(new RegExp(', '))' | ||
end | ||
end | ||
|
||
class ExclusiveRangeNode < Node | ||
def compile | ||
helper :range | ||
|
||
push "$range(" | ||
push expr(@sexp[1]) | ||
push ", " | ||
push expr(@sexp[2]) | ||
push ", false)" | ||
end | ||
end | ||
|
||
class InclusiveRangeNode < Node | ||
def compile | ||
helper :range | ||
|
||
push "$range(" | ||
push expr(@sexp[1]) | ||
push ", " | ||
push expr(@sexp[2]) | ||
push ", true)" | ||
end | ||
end | ||
|
||
end | ||
end |
Oops, something went wrong.
I though we were against the Nodez…