Permalink
Browse files

Added pattern matching

  • Loading branch information...
1 parent 6a41712 commit f5b09be9bb33baeae8c3ffee2cc893ebe500b490 Mike Austin committed Feb 27, 2012
View
@@ -30,6 +30,14 @@ def frame_to_s(value)
return self.to_s()
end
+ def match(receiver, value, locals)
+ if receiver.equal(value).float
+ return {}
+ end
+
+ return nil
+ end
+
def equal(other)
return Value(other && self == other)
end
@@ -11,7 +11,7 @@ def self.instance()
return @instance ||= NilProto.new()
end
- def send_(selector, receiver, args)
+ def send_(selector, receiver, args, locals)
return NilProto.instance
end
View
@@ -36,6 +36,14 @@ def initialize(value)
end
end
+ def to_s()
+ return @frame && @frame.frame_to_s(self)
+ end
+
+ def inspect()
+ return @frame && @frame.frame_inspect(self)
+ end
+
def frame_proto
return @frame.frame_proto
end
@@ -77,6 +85,10 @@ def eval_(receiver, locals)
return @frame.eval_(receiver, locals)
end
+ def match(value, locals)
+ return @frame.match(self, value, locals)
+ end
+
def raw_value()
if @frame == NumberValue.instance.frame
return self.float
@@ -97,6 +109,10 @@ def send_(selector, args, locals)
return @frame.send_(selector, self, args, locals)
end
+ #
+ # Locals methods
+ #
+
def add_local(symbol, value)
return @frame.add_local(symbol, value)
end
@@ -113,6 +129,10 @@ def find_local(symbol)
return @frame.find_local(symbol)
end
+ #
+ # Modules methods
+ #
+
def add_module(symbol, value)
return @frame.add_module(symbol, value)
end
@@ -121,6 +141,10 @@ def find_module(symbol)
return @frame.find_module(symbol)
end
+ #
+ # Methods methods
+ #
+
def add_method(symbol, value)
return @frame.add_method(symbol, value)
end
@@ -133,13 +157,5 @@ def get_method(symbol)
return @frame.get_method(symbol)
end
- def to_s()
- return @frame && @frame.frame_to_s(self)
- end
-
- def inspect()
- return @frame && @frame.frame_inspect(self)
- end
-
end
View
@@ -56,6 +56,12 @@ def to_s()
lexer = Lexer.new($file ? File.open($file) : STDIN)
parser = StatementParser.new(lexer)
+#$file = true
+#lexer2 = Lexer.new(File.open("tests.im"))
+#messages = FileParser.new(lexer2).frame.parse()
+#ExpressionProto(messages).eval_($lobby, $lobby)
+#$file = nil
+
print "] " if !$file
while messages = parser.frame.parse()
if messages != []
@@ -33,6 +33,7 @@ class Lexer < Frame
LitNumberToken, LitStringToken, LitSymbolToken,
CommaToken, DotOperatorToken, VerticalBarToken, DollarSignToken, ColonColonToken,
AssignToken, OperatorToken, IdentifierToken,
+ #OperatorToken, IdentifierToken,
NewlineToken]
def initialize(stream)
@@ -64,6 +64,8 @@ def repeat(token)
def precedence(operator)
case operator.float
+ when :"::"
+ return 0
when :"*", :"/", :"%"
return 5
when :"+", :"-"
@@ -117,13 +119,20 @@ def parse()
identifier = expect(IdentifierToken)
end
end
-
+=begin
if option(AssignToken)
messages += ExpressionParser(@lexer)
return self_message + [AssignMessage(identifier.float, ExpressionProto(messages))]
end
-
+=end
+=begin
+ if option(ColonColonToken)
+ messages2 = ExpressionParser(@lexer)
+
+ return [TypeMessage(LocalMessage(identifier.float), ExpressionProto(messages2))]
+ end
+=end
return self_message + [LocalMessage(identifier.float)]
when VerticalBarToken
return BlockParser.new(@lexer).frame.parse()
@@ -181,8 +190,6 @@ def parse(precedence)
end
return [SendMessage(:slice, arguments)]
- #when NewlineToken
- # return []
end
return []
@@ -229,14 +236,26 @@ def parse()
end
end while option(DollarSignToken)
+ if option(ColonColonToken)
+ messages2 = ExpressionParser(@lexer)
+
+ messages = [TypeMessage(messages[0], ExpressionProto(messages2))]
+ end
+
+ if option(AssignToken)
+ messages2 = ExpressionParser(@lexer)
+
+ messages = [PatternMessage(messages[0], ExpressionProto(messages2))]
+ end
+
option(CommentToken)
expect(NewlineToken, "Expected an expression [2].")
if $file && !peek_token()
return nil
end
-
+#p messages
return messages
end
@@ -251,10 +270,6 @@ def parse(precedence = 0)
expect(OpenParenToken, "Expected '('")
- #if !peek_token().is_a? CloseParenToken
- # expression = ExpressionParser(@lexer)
- #end
-
messages = PrimaryParser(@lexer)
begin
@@ -265,8 +280,6 @@ def parse(precedence = 0)
expect(CloseParenToken, "Expected ')'")
- #messages += expression
-
if messages == []
messages << NothingProto.instance
end
@@ -300,6 +313,12 @@ def parse(precedence)
messages += message
end
+ if option(ColonColonToken)
+ messages2 = ExpressionParser(@lexer)
+
+ messages = [TypeMessage(messages[0], ExpressionProto(messages2))]
+ end
+
return messages
end
@@ -319,7 +338,14 @@ def parse()
if !peek_token().is_a? CloseBracketToken
begin
- items << ExpressionProto(ExpressionParser(@lexer))
+ expr = ExpressionParser(@lexer)
+
+ if expr.size > 1
+ items << ExpressionProto(expr)
+ else
+ items << expr[0]
+ end
+ #items << ExpressionProto(ExpressionParser(@lexer))
end while option(CommaToken)
end
@@ -331,6 +357,27 @@ def parse()
end
+class FileParser < Parser
+
+ def parse()
+ expressions = []
+
+ parser = StatementParser.new(@lexer)
+
+ begin
+ messages = parser.frame.parse()
+
+ if messages != [] && messages != nil
+ expressions << ExpressionProto(messages)
+ end
+ end while messages
+
+ return expressions
+ end
+
+end
+
+
class BodyParser < Parser
def parse()
@@ -250,14 +250,14 @@ def self.read(stream, buffer = "")
char = stream.getc()
if !stream.peek().chr.match(/[:]/)
- stream.unget(char)
+ stream.ungetc(char)
return nil
end
stream.getc();
- return self.new("::")
+ return self.new("::".to_sym)
end
end
@@ -137,6 +137,10 @@ def eval_(receiver, locals)
return receiver.find_local(@selector)
end
+ def match(receiver, value, locals)
+ return { receiver.frame.selector => value }
+ end
+
end
@@ -146,16 +150,12 @@ def ArrayMessage(items)
class ArrayMessage < MessageProto
- def create(items)
- object = super(:array, [items])
+ def create(values)
+ object = super(:array, [values])
return object
end
- def xinitialize(items)
- super(:array, [items])
- end
-
def eval_(receiver, locals)
messageArgs = @args[0].map do |value|
value.eval_(locals, locals)
@@ -164,6 +164,18 @@ def eval_(receiver, locals)
return ArrayProto.instance.frame.create(messageArgs)
end
+ def match(receiver, value, locals)
+ items = receiver.frame.args[0]
+ values = value.frame.array
+
+ bindings = items.zip(values).reduce({}) do |bindings, (item, value)|
+ match = item.match(value, locals)
+ match ? bindings.merge(match) : (return nil)
+ end
+
+ return bindings;
+ end
+
end
@@ -257,3 +269,64 @@ def eval_(receiver, locals)
end
+
+def PatternMessage(lvalue, value)
+ return PatternMessage.instance.frame.create(lvalue, value)
+end
+
+class PatternMessage < MessageProto
+
+ def create(lvalue, value)
+ return super(:pattern, [lvalue, value])
+ end
+
+ def eval_(receiver, locals)
+ #return receiver.set_local(@args[0].frame.selector, @args[1].eval_(locals, locals))
+#p @args[0]
+ bindings = @args[0].frame.match(@args[0], @args[1].eval_(locals, locals), locals)
+#p bindings
+p bindings
+ if !bindings
+ puts "*** Match error: #{@args[0]}"
+
+ return nil
+ end
+
+ bindings.each do |symbol, value|
+ receiver.set_local(symbol, value)
+ end
+
+ nil
+ end
+
+end
+
+
+def TypeMessage(symbol, value)
+ return TypeMessage.instance.frame.create(symbol, value)
+end
+
+class TypeMessage < MessageProto
+
+ def create(symbol, value)
+ return super(:type, [symbol, value])
+ end
+
+ def eval_(receiver, locals)
+ proto = @args[1].eval_(locals, locals)
+
+ return Value(@args[0].eval_(locals, locals).frame_proto.frame == proto.frame)
+ end
+
+ def match(receiver, value, locals)
+ proto = @args[1].eval_(locals, locals)
+
+ if value.frame_is_a(proto)
+ return @args[0].match(value, locals)
+ end
+
+ return nil
+ end
+
+end
+

0 comments on commit f5b09be

Please sign in to comment.