with try-catch working
This commit is contained in:
parent
4e64416397
commit
fdc75144fa
17
code.jaa
17
code.jaa
|
@ -1,5 +1,9 @@
|
||||||
# TODO: switch/case statements
|
# TODO: switch/case statements
|
||||||
# Better block delimiters
|
# Better block delimiters
|
||||||
|
# Flow: For loops, while loops, etc.
|
||||||
|
# Exceptions: throw catch.
|
||||||
|
# When an if statement is the last thing in a function, need to be able to
|
||||||
|
# send the return down to the last expression in the if and else bodies.
|
||||||
|
|
||||||
# Functions:
|
# Functions:
|
||||||
square: x => x * x.
|
square: x => x * x.
|
||||||
|
@ -11,7 +15,7 @@ odd: x => x % 2 is 0.
|
||||||
even: x => x % 2 aint 0.
|
even: x => x % 2 aint 0.
|
||||||
|
|
||||||
run_loop: =>
|
run_loop: =>
|
||||||
fire_events(e => e.stopPropagation().)
|
fire_events( e => e.stopPropagation(). )
|
||||||
listen()
|
listen()
|
||||||
wait().
|
wait().
|
||||||
|
|
||||||
|
@ -21,7 +25,7 @@ object_literal: {one: 1, two: 2, three: 3}
|
||||||
multiline_object: {
|
multiline_object: {
|
||||||
pi: 3.14159
|
pi: 3.14159
|
||||||
list: [1, 2, 3, 4]
|
list: [1, 2, 3, 4]
|
||||||
three: 3
|
three: new Idea()
|
||||||
inner_obj: {
|
inner_obj: {
|
||||||
freedom: => _.freedom().
|
freedom: => _.freedom().
|
||||||
}
|
}
|
||||||
|
@ -56,6 +60,11 @@ wine &&= cheese
|
||||||
# Nested property access and calls.
|
# Nested property access and calls.
|
||||||
((moon.turn(360))).shapes[3].move({x: 45, y: 30}).position
|
((moon.turn(360))).shapes[3].move({x: 45, y: 30}).position
|
||||||
|
|
||||||
|
# Try/Catch/Finally.
|
||||||
|
try
|
||||||
|
all_hell_breaks_loose()
|
||||||
|
dogs_and_cats_living_together()
|
||||||
|
catch error
|
||||||
|
print( error ).
|
||||||
|
|
||||||
|
try all_hell_breaks_loose() catch error then print(error).
|
||||||
|
|
|
@ -8,15 +8,15 @@ dc.model.Document: dc.Model.extend({
|
||||||
# The import process will take care of this in the future, but the inline
|
# The import process will take care of this in the future, but the inline
|
||||||
# version of the summary has all runs of whitespace squeezed out.
|
# version of the summary has all runs of whitespace squeezed out.
|
||||||
displaySummary: =>
|
displaySummary: =>
|
||||||
text: this.get('highlight') or this.get('summary')
|
text: this.get('highlight') or this.get('summary') or ''
|
||||||
if text then text.replace(/\s+/g, ' ') else ''..
|
text and text.replace(/\s+/g, ' ').
|
||||||
|
|
||||||
# Return a list of the document's metadata. Think about caching this on the
|
# Return a list of the document's metadata. Think about caching this on the
|
||||||
# document by binding to Metadata, instead of on-the-fly.
|
# document by binding to Metadata, instead of on-the-fly.
|
||||||
metadata: =>
|
metadata: =>
|
||||||
docId: this.id
|
docId: this.id
|
||||||
_.select(Metadata.models()
|
_.select(Metadata.models()
|
||||||
datum => _.any(datum.get('instances')
|
meta => _.any(meta.get('instances')
|
||||||
instance => instance.document_id == docId.).).
|
instance => instance.document_id == docId.).).
|
||||||
|
|
||||||
bookmark: pageNumber =>
|
bookmark: pageNumber =>
|
||||||
|
|
32
grammar.y
32
grammar.y
|
@ -10,6 +10,7 @@ token TRUE FALSE NULL
|
||||||
token IDENTIFIER PROPERTY_ACCESS
|
token IDENTIFIER PROPERTY_ACCESS
|
||||||
token CODE PARAM
|
token CODE PARAM
|
||||||
token NEW RETURN
|
token NEW RETURN
|
||||||
|
token TRY CATCH FINALLY THROW
|
||||||
|
|
||||||
prechigh
|
prechigh
|
||||||
nonassoc UMINUS NOT '!'
|
nonassoc UMINUS NOT '!'
|
||||||
|
@ -51,16 +52,14 @@ rule
|
||||||
# All types of expressions in our language
|
# All types of expressions in our language
|
||||||
Expression:
|
Expression:
|
||||||
Literal
|
Literal
|
||||||
| Variable
|
| Value
|
||||||
| Call
|
| Call
|
||||||
| Assign
|
| Assign
|
||||||
| Object
|
|
||||||
| Code
|
| Code
|
||||||
| Operation
|
| Operation
|
||||||
| Array
|
|
||||||
| If
|
| If
|
||||||
|
| Try
|
||||||
| Return
|
| Return
|
||||||
| Parenthetical
|
|
||||||
;
|
;
|
||||||
|
|
||||||
# All tokens that can terminate an expression
|
# All tokens that can terminate an expression
|
||||||
|
@ -81,7 +80,7 @@ rule
|
||||||
|
|
||||||
# Assign to a variable
|
# Assign to a variable
|
||||||
Assign:
|
Assign:
|
||||||
Variable ":" Expression { result = AssignNode.new(val[0], val[2]) }
|
Value ":" Expression { result = AssignNode.new(val[0], val[2]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
# Assignment within an object literal.
|
# Assignment within an object literal.
|
||||||
|
@ -145,11 +144,13 @@ rule
|
||||||
| ParamList "," PARAM { result = val[0] << val[2] }
|
| ParamList "," PARAM { result = val[0] << val[2] }
|
||||||
;
|
;
|
||||||
|
|
||||||
Variable:
|
Value:
|
||||||
IDENTIFIER { result = VariableNode.new(val) }
|
IDENTIFIER { result = ValueNode.new(val) }
|
||||||
| Variable Accessor { result = val[0] << val[1] }
|
| Array { result = ValueNode.new(val) }
|
||||||
| Invocation Accessor { result = VariableNode.new(val[0], [val[1]]) }
|
| Object { result = ValueNode.new(val) }
|
||||||
| Parenthetical Accessor { result = VariableNode.new(val[0], [val[1]]) }
|
| Parenthetical { result = ValueNode.new(val) }
|
||||||
|
| Value Accessor { result = val[0] << val[1] }
|
||||||
|
| Invocation Accessor { result = ValueNode.new(val[0], [val[1]]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
Accessor:
|
Accessor:
|
||||||
|
@ -179,11 +180,11 @@ rule
|
||||||
# A method call.
|
# A method call.
|
||||||
Call:
|
Call:
|
||||||
Invocation { result = val[0] }
|
Invocation { result = val[0] }
|
||||||
| NEW Invocation { result = val[0].new_instance }
|
| NEW Invocation { result = val[1].new_instance }
|
||||||
;
|
;
|
||||||
|
|
||||||
Invocation:
|
Invocation:
|
||||||
Variable "(" ArgList ")" { result = CallNode.new(val[0], val[2]) }
|
Value "(" ArgList ")" { result = CallNode.new(val[0], val[2]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
# An Array.
|
# An Array.
|
||||||
|
@ -212,6 +213,13 @@ rule
|
||||||
ELSE Expressions "." { result = IfNode.new(val[1], val[3], val[6]) }
|
ELSE Expressions "." { result = IfNode.new(val[1], val[3], val[6]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Try:
|
||||||
|
TRY Expressions CATCH IDENTIFIER
|
||||||
|
Terminator Expressions "." { result = TryNode.new(val[1], val[3], val[5]) }
|
||||||
|
| TRY Expression CATCH IDENTIFIER
|
||||||
|
THEN Expression "." { result = TryNode.new(val[1], val[3], val[5]) }
|
||||||
|
;
|
||||||
|
|
||||||
Parenthetical:
|
Parenthetical:
|
||||||
"(" Expressions ")" { result = ParentheticalNode.new(val[1]) }
|
"(" Expressions ")" { result = ParentheticalNode.new(val[1]) }
|
||||||
;
|
;
|
||||||
|
|
3
lexer.rb
3
lexer.rb
|
@ -3,7 +3,8 @@ class Lexer
|
||||||
KEYWORDS = ["if", "else", "then",
|
KEYWORDS = ["if", "else", "then",
|
||||||
"true", "false", "null",
|
"true", "false", "null",
|
||||||
"and", "or", "is", "aint", "not",
|
"and", "or", "is", "aint", "not",
|
||||||
"new", "return"]
|
"new", "return",
|
||||||
|
"try", "catch", "finally", "throw"]
|
||||||
|
|
||||||
IDENTIFIER = /\A([a-zA-Z$_]\w*)/
|
IDENTIFIER = /\A([a-zA-Z$_]\w*)/
|
||||||
NUMBER = /\A([0-9]+(\.[0-9]+)?)/
|
NUMBER = /\A([0-9]+(\.[0-9]+)?)/
|
||||||
|
|
25
nodes.rb
25
nodes.rb
|
@ -70,6 +70,7 @@ class CallNode < Node
|
||||||
|
|
||||||
def new_instance
|
def new_instance
|
||||||
@new = true
|
@new = true
|
||||||
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile(indent, last=false)
|
def compile(indent, last=false)
|
||||||
|
@ -79,7 +80,7 @@ class CallNode < Node
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class VariableNode < Node
|
class ValueNode < Node
|
||||||
def initialize(name, properties=[])
|
def initialize(name, properties=[])
|
||||||
@name, @properties = name, properties
|
@name, @properties = name, properties
|
||||||
end
|
end
|
||||||
|
@ -243,6 +244,28 @@ class IfNode < Node
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class TryNode < Node
|
||||||
|
def initialize(try, error, recovery)
|
||||||
|
@try, @error, @recovery = try, error, recovery
|
||||||
|
end
|
||||||
|
|
||||||
|
def line_ending
|
||||||
|
''
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile(indent, last=false)
|
||||||
|
@try.is_a?(Nodes) ? compile_expressions(indent) : compile_raw(indent)
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile_expressions(indent)
|
||||||
|
"try {\n#{@try.compile(indent + TAB)}\n#{indent}} catch (#{@error}) {\n#{@recovery.compile(indent + TAB)}\n#{indent}}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile_raw(indent)
|
||||||
|
"try {\n#{indent}#{TAB}#{@try.compile(indent)}#{@try.line_ending}\n#{indent}} catch (#{@error}) {\n#{indent}#{TAB}#{@recovery.compile(indent)}#{@recovery.line_ending}\n#{indent}}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class ParentheticalNode < Node
|
class ParentheticalNode < Node
|
||||||
def initialize(expressions)
|
def initialize(expressions)
|
||||||
@expressions = expressions
|
@expressions = expressions
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
# Examples from the Poignant Guide.
|
||||||
|
|
||||||
|
# ['toast', 'cheese', 'wine'].each { |food| print food.capitalize }
|
||||||
|
|
||||||
|
['toast', 'wine', 'cheese'].each( food => print(food.capitalize()). )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# class LotteryTicket
|
||||||
|
# def picks; @picks; end
|
||||||
|
# def picks=(var); @picks = var; end
|
||||||
|
# def purchased; @purchased; end
|
||||||
|
# def purchased=(var); @purchased = var; end
|
||||||
|
# end
|
||||||
|
|
||||||
|
LotteryTicket: {
|
||||||
|
get_picks: => this.picks.
|
||||||
|
set_picks: nums => this.picks: nums.
|
||||||
|
get_purchase: => this.purchase.
|
||||||
|
set_purchase: amount => this.purchase: amount.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# module WishScanner
|
||||||
|
# def scan_for_a_wish
|
||||||
|
# wish = self.read.detect do |thought|
|
||||||
|
# thought.index( 'wish: ' ) == 0
|
||||||
|
# end
|
||||||
|
# wish.gsub( 'wish: ', '' )
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
|
WishScanner : {
|
||||||
|
scan_for_a_wish: =>
|
||||||
|
wish: this.read().detect( thought => thought.index('wish: ') is 0. )
|
||||||
|
wish.replace('wish: ', '').
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# class Creature
|
||||||
|
#
|
||||||
|
# # This method applies a hit taken during a fight.
|
||||||
|
# def hit( damage )
|
||||||
|
# p_up = rand( charisma )
|
||||||
|
# if p_up % 9 == 7
|
||||||
|
# @life += p_up / 4
|
||||||
|
# puts "[#{ self.class } magick powers up #{ p_up }!]"
|
||||||
|
# end
|
||||||
|
# @life -= damage
|
||||||
|
# puts "[#{ self.class } has died.]" if @life <= 0
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # This method takes one turn in a fight.
|
||||||
|
# def fight( enemy, weapon )
|
||||||
|
# if life <= 0
|
||||||
|
# puts "[#{ self.class } is too dead to fight!]"
|
||||||
|
# return
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # Attack the opponent
|
||||||
|
# your_hit = rand( strength + weapon )
|
||||||
|
# puts "[You hit with #{ your_hit } points of damage!]"
|
||||||
|
# enemy.hit( your_hit )
|
||||||
|
#
|
||||||
|
# # Retaliation
|
||||||
|
# p enemy
|
||||||
|
# if enemy.life > 0
|
||||||
|
# enemy_hit = rand( enemy.strength + enemy.weapon )
|
||||||
|
# puts "[Your enemy hit with #{ enemy_hit } points of damage!]"
|
||||||
|
# self.hit( enemy_hit )
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# end
|
||||||
|
|
||||||
|
Creature : {
|
||||||
|
|
||||||
|
# This method applies a hit taken during a fight.
|
||||||
|
hit: damage =>
|
||||||
|
p_up: Math.rand( this.charisma )
|
||||||
|
if p_up % 9 is 7
|
||||||
|
this.life += p_up / 4
|
||||||
|
puts( "[" + this.name + " magick powers up " + p_up + "!]" ).
|
||||||
|
this.life -= damage
|
||||||
|
if this.life <= 0 then puts( "[" + this.name + " has died.]" )..
|
||||||
|
|
||||||
|
# This method takes one turn in a fight.
|
||||||
|
fight: enemy, weapon =>
|
||||||
|
if this.life <= 0 then return puts( "[" + this.name + "is too dead to fight!]" ).
|
||||||
|
|
||||||
|
# Attack the opponent.
|
||||||
|
your_hit: Math.rand( this.strength + weapon )
|
||||||
|
puts( "[You hit with " + your_hit + "points of damage!]" )
|
||||||
|
enemy.hit( your_hit )
|
||||||
|
|
||||||
|
# Retaliation.
|
||||||
|
puts( enemy )
|
||||||
|
if enemy.life > 0
|
||||||
|
enemy_hit: Math.rand( enemy.strength + enemy.weapon )
|
||||||
|
puts( "[Your enemy hit with " + enemy_hit + "points of damage!]" )
|
||||||
|
this.hit( enemy_hit ).
|
||||||
|
this.
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue