Skip to content

Commit

Permalink
sync (#1)
Browse files Browse the repository at this point in the history
* fix class vars initialization (issue #141)

Only addMethods of outputEs5 fixed

* Update output.pyj

* fix issue #141 for ES6 too

Now  with_class_vars_init()  is the  method of output

* Update output.pyj

* Update classes.pyj

* fix Fibonacci typo

* added promise support

* version bump

* fixing find_if bug

* fixed string format bug
  • Loading branch information
valq7711 committed Jul 1, 2017
1 parent b374852 commit 91b53db
Show file tree
Hide file tree
Showing 7 changed files with 1,951 additions and 1,649 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -7,7 +7,7 @@ RapydScript

What is RapydScript?
--------------------
RapydScript is a pre-compiler for JavaScript. The syntax is very similar to Python, but allows JavaScript as well. This project was written as a cleaner alternative to CoffeeScript. Here is a quick example of a high-performance Fibinacci function in RapydScript and the JavaScript it produces after compilation:
RapydScript is a pre-compiler for JavaScript. The syntax is very similar to Python, but allows JavaScript as well. This project was written as a cleaner alternative to CoffeeScript. Here is a quick example of a high-performance Fibonacci function in RapydScript and the JavaScript it produces after compilation:

```python
def memoize(f):
Expand Down
3,497 changes: 1,873 additions & 1,624 deletions lib/rapydscript.js

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Expand Up @@ -13,10 +13,11 @@
"test": "bin/rapydscript --test",
"test6": "bin/rapydscript --test --es6",
"preversion": "npm test",
"postversion": "npm publish",
"version": "",
"postversion": "git push && npm publish",
"build-self": "bin/rapydscript --self"
},
"version": "0.5.55",
"version": "0.5.58",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12.0"
Expand Down
3 changes: 2 additions & 1 deletion src/ast.pyj
Expand Up @@ -47,6 +47,7 @@ class Token(AST):
"""
properties = {
'type': 'The type of the token',
'subtype': 'The subtype of the token',
'value': 'The value of the token',
'line': 'The line number at which the token occurs',
'col': 'The column number at which the token occurs',
Expand Down Expand Up @@ -172,7 +173,7 @@ class Debugger(Statement): "Represents a debugger statement"
class Directive(Statement):
'Represents a directive, like "use strict";'
properties = {
value: "[string] The value of this directive as a plain string (it's not an String!)",
value: "[string] The value of this directive as a plain string (it's not a String!)",
scope: "[Scope/S] The scope that this directive affects"
}

Expand Down
54 changes: 49 additions & 5 deletions src/output.pyj
Expand Up @@ -337,6 +337,33 @@ def Stream(options):
print_("]")
return ret


# class vars should be evaluated before Object.defineProperties(...)
# nice to have a wrapper:
# (function()
# init/eval class vars, so they can refer to each other
# Object.defineProperties(...) - using predefined variables
# )()
def with_class_vars_init(vars, def_prop):
return def(obj):
output = this
output.with_parens(def():
output.print("function()")
output.with_block(def():
vars.forEach(def(v, i):
output.indent()
output.assign('var '+ v.name)
v.value(output)
output.end_statement()
)
output.indent()
# def_prop = output.addProperties('prototype', methodsAndVars)
def_prop.call(output, obj)
output.end_statement()
)
)
output.print("()")

def comma():
print_(",")
space()
Expand Down Expand Up @@ -481,6 +508,7 @@ def Stream(options):
with_indent: with_indent,
with_block: with_block,
with_parens: with_parens,
with_class_vars_init: with_class_vars_init,
spaced: spaced,
end_statement: end_statement,
addProperty: addProperty,
Expand Down Expand Up @@ -1544,18 +1572,28 @@ def Stream(options):
def addClassVariables():
# these were somehow omitted from ES6 standard, so we'll have to handle them ourselves, the messy way
properties = {}
# class vars should be evaluated before Object.defineProperties(...)
# order of vars is important! so we need an Array of {name: ... , value: ...}
class_vars = []
if self.docstring:
properties['__doc__'] = def(output): output.print_string(self.docstring)
self.body.forEach(def(stmt, i):
if isinstance(stmt, ast.SimpleStatement) and isinstance(stmt.body, ast.Assign) and stmt.body.operator is '=':
# naively assume left side will not be an expression
properties[stmt.body.left.name] = def(output):
stmt.body.right.print(output)
output.print(stmt.body.left.name)
output.newline()
class_vars.push({
name: stmt.body.left.name,
value: def(output): stmt.body.right.print(output)
})
)

if Object.keys(properties).length:
return output.addProperties('prototype', properties)
def_class_vars = output.addProperties('prototype', properties)
if class_vars.length:
def_class_vars = output.with_class_vars_init(class_vars, def_class_vars)
return def_class_vars
return None

# new ES6 classes
Expand Down Expand Up @@ -1680,6 +1718,9 @@ def Stream(options):
# actual methods, and class variables
methodsAndVars = {}
staticMethods = {}
# class vars should be evaluated before Object.defineProperties(...)
# order of vars is important! so we need an Array of {name: ... , value: ...}
class_vars = []
if self.docstring:
methodsAndVars['__doc__'] = def(output): output.print_string(self.docstring)
self.body.forEach(def(stmt, i):
Expand All @@ -1693,15 +1734,18 @@ def Stream(options):
elif isinstance(stmt, ast.SimpleStatement) and isinstance(stmt.body, ast.Assign) and stmt.body.operator is '=':
# class variable
methodsAndVars[stmt.body.left.name] = def(output):
stmt.body.right.print(output)

output.print(stmt.body.left.name)
class_vars.push({ name: stmt.body.left.name,
value: def(output): stmt.body.right.print(output);})
elif isinstance(stmt, ast.Class):
console.error('Nested classes aren\'t supported yet')
)

methodAndOutput = None
if Object.keys(methodsAndVars).length:
methodAndVarOutput = output.addProperties('prototype', methodsAndVars)
if class_vars.length:
methodAndVarOutput = output.with_class_vars_init(class_vars, methodAndVarOutput)

staticMethodOutput = None
if Object.keys(staticMethods).length:
Expand Down
24 changes: 19 additions & 5 deletions src/parser.pyj
Expand Up @@ -16,7 +16,7 @@
**********************************************************************
"""

from utils import makePredicate, defaults, ImportError, js_error, RAPYD_PREFIX
from utils import makePredicate, defaults, ImportError, js_error, RAPYD_PREFIX, find_if
import ast
import tokenizer

Expand All @@ -42,6 +42,10 @@ NATIVE_CLASSES = {
"defineProperties",
"getPrototypeOf", # ES6
"setPrototypeOf", # ES6

# experimental
"values",
"entries"
]
},
'String': {
Expand All @@ -58,7 +62,9 @@ NATIVE_CLASSES = {
static: [ "UTC", "now", "parse" ]
},
'Boolean': {},
'ArrayBuffer': {},
'ArrayBuffer': {
static: [ "isView", "transfer" ]
},
'DataView': {},
'Float32Array': {},
'Float64Array': {},
Expand All @@ -73,6 +79,14 @@ NATIVE_CLASSES = {
'WeakMap': {}, # ES6
'Set': {}, # ES6
'WeakSet': {}, # ES6
'Promise': { # ES6
static: [
"all",
"race",
"reject",
"resolve"
]
},

# baselib
"AssertionError": {},
Expand Down Expand Up @@ -2113,20 +2127,20 @@ def parse($TEXT, options):
if right:
if right[0] is '[': right = 'Array'
elif right[0] is '{': right = 'Object'
raise croak("cannot perform binary '" + op + "' operation on incompatbile elements of type " + left + " and " + right + "")
raise croak("cannot perform binary '" + op + "' operation on incompatible elements of type " + left + " and " + right + "")
return astElement

def validateUnary(astElement):
# check that the prefix is compatible with the element
element = astElement.expression.resolveType(S.in_scope)
op = astElement.operator
if not element:
if op is not '!': raise croak("cannot perform unary '" + op + "' operation on incompatbile element of type " + element)
if op is not '!': raise croak("cannot perform unary '" + op + "' operation on incompatible element of type " + element)
elif element not in ['Number', '?'] and op in ['+', '-'] or element[0] not in ['[', '{', '?'] and op is '*':
# make the representations a bit more human-friendly
if element[0] is '[': element = 'Array'
elif element[0] is '{': element = 'Object'
raise croak("cannot perform unary '" + op + "' operation on incompatbile element of type " + element)
raise croak("cannot perform unary '" + op + "' operation on incompatible element of type " + element)
return astElement

def validateCallArgs(astElement):
Expand Down
15 changes: 4 additions & 11 deletions test/basic/classes.pyj
Expand Up @@ -177,17 +177,10 @@ assert.equal(m.pi, 3.14)
class C:
a = 1
b = 1
c = 2
d = 1
# previously these were actually instance variables, they are now class vars
# arithmetic here is no longer supported, I may revisit this later
#class C:
# a = b = 1
# c = a + b
# if True:
# d = 1
# else:
# d = 2
#Class variables can reference each other during initialization
c = a + b
#but complex logic is not allowed, all statements must be assignments
d = (def(): if c > 0: return 1;)() or 0
c = C()
assert.deepEqual([c.a, c.b, c.c, c.d], [1, 1, 2, 1])

Expand Down

0 comments on commit 91b53db

Please sign in to comment.