Skip to content

Commit

Permalink
Added class support to lox2python
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Berezin committed Jun 25, 2019
1 parent e37a1e3 commit b207b35
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 10 deletions.
19 changes: 19 additions & 0 deletions hi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Doughnut():
def __init__(this, name):
this.name = name
def cook(this):
name = ""
if this.name:
name = this.name + " "
print "You fry the " + name + "Doughnut until golden brown."
class BostonCream(Doughnut):
def __init__(this):
Doughnut.__init__(this, "Boston Cream")
Doughnut("Cruller").cook()
BostonCream().cook()
def hello():
print "Would you like some breakfast?"
print BostonCream
print Doughnut
print BostonCream()
print hello
1 change: 0 additions & 1 deletion transpilers/lox.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const {
Call,
Literal,
While,
// @TODO: Support Classes
Class,
Get,
Set: SetExpr,
Expand Down
61 changes: 52 additions & 9 deletions transpilers/python.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ const {
Call,
Literal,
While,
// @TODO: Support Classes
// Class,
// Get,
// Set,
Class,
Get,
Set: SetExpr,
Super,
This,
Grouping,
Return,
LoxFunction,
Expand All @@ -24,6 +25,8 @@ const {
// const condChar = (condition, replacer = ' ') => condition ? replacer : ''
const indentation = (scope, options) => options.indent.repeat(scope)

let lastSuperclass = 'super'

const ASTNodeMap = new Map()

// Declarations
Expand All @@ -48,13 +51,19 @@ ASTNodeMap.set(Condition, ({ condition, thenBranch, elseBranch }, scope, options
return conditionSection + thenSection + (elseSection ? `\n${indentation(scope, options)}else:\n${elseSection}` : '')
})

ASTNodeMap.set(LoxFunction, ({ bodyStatements: body, name: { lexeme: name }, params}, scope, options) => {
const printFunction = ({ bodyStatements: body, name: { lexeme: name }, params}, scope, options, func = true) => {
const parameters = params.map(token => token.lexeme)
if (!func) {
parameters.unshift('this')
if (name === 'init') name = '__init__'
}
const head = indentation(scope, options) + `def ${name}(${parameters.join(', ')}):`
// Python doesn't have blank function declarations
const fnBody = body.length > 0 ? body.map(stmt => loxToPython2(stmt, scope + 1, options)) : [indentation(scope + 1, options) + 'pass']
return [head, ...fnBody].join('\n')
})
}

ASTNodeMap.set(LoxFunction, printFunction)

ASTNodeMap.set(While, ({ body, condition }, scope, options) => {
const cond = loxToPython2(condition)
Expand All @@ -63,6 +72,38 @@ ASTNodeMap.set(While, ({ body, condition }, scope, options) => {
return conditionSection + bodySection
})

ASTNodeMap.set(Class, ({ name, superclass, methods }, scope, options) => {
let superclassStr = '()'
if (superclass) {
lastSuperclass = superclass.name.lexeme
superclassStr = `(${superclass.name.lexeme})`
}
const head = indentation(scope, options) + `class ${name.lexeme}${superclassStr}:`
let body = methods.map(node => printFunction(node, scope + 1, options, false))
return [head, ...body].join('\n')
})

ASTNodeMap.set(Get, ({ name, object }, scope, options) => {
let nameStr = name.lexeme ? name.lexeme : loxToPython2(name, scope, options, false)
const objectStr = loxToPython2(object, scope, options, false)
return objectStr + '.' + nameStr
})

ASTNodeMap.set(SetExpr, ({ name, object, value }, scope, options) => {
const nameStr = name.lexeme ? name.lexeme : loxToPython2(name, scope, options, false)
const objectStr = loxToPython2(object, scope, options, false)
const val = loxToPython2(value, scope, options)
return objectStr + '.' + nameStr + ' = ' + val
})

ASTNodeMap.set(Super, ({ method: { lexeme: methodName }}) => {
if (methodName === 'init') methodName = '__init__'
return `${lastSuperclass}.${methodName}`
})

ASTNodeMap.set(This, ({ keyword }) => keyword.lexeme)


ASTNodeMap.set(Block, ({ statements }, scope, options, initialIndent) => statements.map(stmt => loxToPython2(stmt, scope, options, initialIndent)).join('\n'))

// Expressions
Expand Down Expand Up @@ -90,9 +131,11 @@ ASTNodeMap.set(Unary, node => {


ASTNodeMap.set(Call, node => {
const args = node.arguments.map(args => loxToPython2(args)).join(', ')
const args = node.arguments.map(args => loxToPython2(args))
const callee = loxToPython2(node.callee)
return `${callee}(${args})`
if (String(callee).endsWith('__init__')) args.unshift('this')
const argsStr = args.join(', ')
return `${callee}(${argsStr})`
})

ASTNodeMap.set(Assignment, node => {
Expand All @@ -119,7 +162,7 @@ const loxToPython2 = (node, scope = 0, optionsOverride = {}) => {
if (ASTNodeMap.has(node.constructor)) {
return ASTNodeMap.get(node.constructor)(node, scope, options)
}
throw new Error(`Don't support classes yet`, node.constructor)
throw new Error(`Don't support that AST node yet`, node.constructor)
}

module.exports = {
Expand Down

0 comments on commit b207b35

Please sign in to comment.