mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
with try-catch working
This commit is contained in:
parent
4e64416397
commit
fdc75144fa
7 changed files with 690 additions and 482 deletions
17
code.jaa
17
code.jaa
|
@ -1,5 +1,9 @@
|
|||
# TODO: switch/case statements
|
||||
# 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:
|
||||
square: x => x * x.
|
||||
|
@ -11,7 +15,7 @@ odd: x => x % 2 is 0.
|
|||
even: x => x % 2 aint 0.
|
||||
|
||||
run_loop: =>
|
||||
fire_events(e => e.stopPropagation().)
|
||||
fire_events( e => e.stopPropagation(). )
|
||||
listen()
|
||||
wait().
|
||||
|
||||
|
@ -21,7 +25,7 @@ object_literal: {one: 1, two: 2, three: 3}
|
|||
multiline_object: {
|
||||
pi: 3.14159
|
||||
list: [1, 2, 3, 4]
|
||||
three: 3
|
||||
three: new Idea()
|
||||
inner_obj: {
|
||||
freedom: => _.freedom().
|
||||
}
|
||||
|
@ -56,6 +60,11 @@ wine &&= cheese
|
|||
# Nested property access and calls.
|
||||
((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
|
||||
# version of the summary has all runs of whitespace squeezed out.
|
||||
displaySummary: =>
|
||||
text: this.get('highlight') or this.get('summary')
|
||||
if text then text.replace(/\s+/g, ' ') else ''..
|
||||
text: this.get('highlight') or this.get('summary') or ''
|
||||
text and text.replace(/\s+/g, ' ').
|
||||
|
||||
# Return a list of the document's metadata. Think about caching this on the
|
||||
# document by binding to Metadata, instead of on-the-fly.
|
||||
metadata: =>
|
||||
docId: this.id
|
||||
_.select(Metadata.models()
|
||||
datum => _.any(datum.get('instances')
|
||||
meta => _.any(meta.get('instances')
|
||||
instance => instance.document_id == docId.).).
|
||||
|
||||
bookmark: pageNumber =>
|
||||
|
|
32
grammar.y
32
grammar.y
|
@ -10,6 +10,7 @@ token TRUE FALSE NULL
|
|||
token IDENTIFIER PROPERTY_ACCESS
|
||||
token CODE PARAM
|
||||
token NEW RETURN
|
||||
token TRY CATCH FINALLY THROW
|
||||
|
||||
prechigh
|
||||
nonassoc UMINUS NOT '!'
|
||||
|
@ -51,16 +52,14 @@ rule
|
|||
# All types of expressions in our language
|
||||
Expression:
|
||||
Literal
|
||||
| Variable
|
||||
| Value
|
||||
| Call
|
||||
| Assign
|
||||
| Object
|
||||
| Code
|
||||
| Operation
|
||||
| Array
|
||||
| If
|
||||
| Try
|
||||
| Return
|
||||
| Parenthetical
|
||||
;
|
||||
|
||||
# All tokens that can terminate an expression
|
||||
|
@ -81,7 +80,7 @@ rule
|
|||
|
||||
# Assign to a variable
|
||||
Assign:
|
||||
Variable ":" Expression { result = AssignNode.new(val[0], val[2]) }
|
||||
Value ":" Expression { result = AssignNode.new(val[0], val[2]) }
|
||||
;
|
||||
|
||||
# Assignment within an object literal.
|
||||
|
@ -145,11 +144,13 @@ rule
|
|||
| ParamList "," PARAM { result = val[0] << val[2] }
|
||||
;
|
||||
|
||||
Variable:
|
||||
IDENTIFIER { result = VariableNode.new(val) }
|
||||
| Variable Accessor { result = val[0] << val[1] }
|
||||
| Invocation Accessor { result = VariableNode.new(val[0], [val[1]]) }
|
||||
| Parenthetical Accessor { result = VariableNode.new(val[0], [val[1]]) }
|
||||
Value:
|
||||
IDENTIFIER { result = ValueNode.new(val) }
|
||||
| Array { result = ValueNode.new(val) }
|
||||
| Object { result = ValueNode.new(val) }
|
||||
| Parenthetical { result = ValueNode.new(val) }
|
||||
| Value Accessor { result = val[0] << val[1] }
|
||||
| Invocation Accessor { result = ValueNode.new(val[0], [val[1]]) }
|
||||
;
|
||||
|
||||
Accessor:
|
||||
|
@ -179,11 +180,11 @@ rule
|
|||
# A method call.
|
||||
Call:
|
||||
Invocation { result = val[0] }
|
||||
| NEW Invocation { result = val[0].new_instance }
|
||||
| NEW Invocation { result = val[1].new_instance }
|
||||
;
|
||||
|
||||
Invocation:
|
||||
Variable "(" ArgList ")" { result = CallNode.new(val[0], val[2]) }
|
||||
Value "(" ArgList ")" { result = CallNode.new(val[0], val[2]) }
|
||||
;
|
||||
|
||||
# An Array.
|
||||
|
@ -212,6 +213,13 @@ rule
|
|||
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:
|
||||
"(" Expressions ")" { result = ParentheticalNode.new(val[1]) }
|
||||
;
|
||||
|
|
3
lexer.rb
3
lexer.rb
|
@ -3,7 +3,8 @@ class Lexer
|
|||
KEYWORDS = ["if", "else", "then",
|
||||
"true", "false", "null",
|
||||
"and", "or", "is", "aint", "not",
|
||||
"new", "return"]
|
||||
"new", "return",
|
||||
"try", "catch", "finally", "throw"]
|
||||
|
||||
IDENTIFIER = /\A([a-zA-Z$_]\w*)/
|
||||
NUMBER = /\A([0-9]+(\.[0-9]+)?)/
|
||||
|
|
25
nodes.rb
25
nodes.rb
|
@ -70,6 +70,7 @@ class CallNode < Node
|
|||
|
||||
def new_instance
|
||||
@new = true
|
||||
self
|
||||
end
|
||||
|
||||
def compile(indent, last=false)
|
||||
|
@ -79,7 +80,7 @@ class CallNode < Node
|
|||
end
|
||||
end
|
||||
|
||||
class VariableNode < Node
|
||||
class ValueNode < Node
|
||||
def initialize(name, properties=[])
|
||||
@name, @properties = name, properties
|
||||
end
|
||||
|
@ -243,6 +244,28 @@ class IfNode < Node
|
|||
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
|
||||
def initialize(expressions)
|
||||
@expressions = expressions
|
||||
|
|
106
poignant.jaa
Normal file
106
poignant.jaa
Normal file
|
@ -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 a new issue