Skip to content

Commit

Permalink
Adding support for natives
Browse files Browse the repository at this point in the history
  • Loading branch information
tesonep committed May 21, 2016
1 parent 3abdc3a commit 3fc6d45
Show file tree
Hide file tree
Showing 28 changed files with 631 additions and 248 deletions.
Original file line number Diff line number Diff line change
@@ -1,41 +1,57 @@
package org.uqbar.project.wollok.codeGenerator

import org.eclipse.emf.ecore.EObject

import org.uqbar.project.wollok.codeGenerator.model.Assignment
import org.uqbar.project.wollok.codeGenerator.model.ClassDefinition
import org.uqbar.project.wollok.codeGenerator.model.ConstructorCall
import org.uqbar.project.wollok.codeGenerator.model.Context
import org.uqbar.project.wollok.codeGenerator.model.Expression
import org.uqbar.project.wollok.codeGenerator.model.IfExpression
import org.uqbar.project.wollok.codeGenerator.model.MessageSend
import org.uqbar.project.wollok.codeGenerator.model.Method
import org.uqbar.project.wollok.codeGenerator.model.NamedObject
import org.uqbar.project.wollok.codeGenerator.model.NumberLiteral
import org.uqbar.project.wollok.codeGenerator.model.Parameter
import org.uqbar.project.wollok.codeGenerator.model.Program
import org.uqbar.project.wollok.codeGenerator.model.Return
import org.uqbar.project.wollok.codeGenerator.model.Self
import org.uqbar.project.wollok.codeGenerator.model.Variable
import org.uqbar.project.wollok.codeGenerator.model.VariableRef
import org.uqbar.project.wollok.interpreter.WollokClassFinder
import org.uqbar.project.wollok.wollokDsl.WAssignment
import org.uqbar.project.wollok.wollokDsl.WBinaryOperation
import org.uqbar.project.wollok.wollokDsl.WBlockExpression
import org.uqbar.project.wollok.wollokDsl.WClass
import org.uqbar.project.wollok.wollokDsl.WConstructorCall
import org.uqbar.project.wollok.wollokDsl.WFile
import org.uqbar.project.wollok.wollokDsl.WIfExpression
import org.uqbar.project.wollok.wollokDsl.WMemberFeatureCall
import org.uqbar.project.wollok.wollokDsl.WMethodDeclaration
import org.uqbar.project.wollok.wollokDsl.WNamedObject
import org.uqbar.project.wollok.wollokDsl.WNumberLiteral
import org.uqbar.project.wollok.wollokDsl.WParameter
import org.uqbar.project.wollok.wollokDsl.WProgram
import org.uqbar.project.wollok.wollokDsl.WReturnExpression
import org.uqbar.project.wollok.wollokDsl.WSelf
import org.uqbar.project.wollok.wollokDsl.WStringLiteral
import org.uqbar.project.wollok.wollokDsl.WUnaryOperation
import org.uqbar.project.wollok.wollokDsl.WVariableDeclaration
import org.uqbar.project.wollok.wollokDsl.WVariableReference
import org.uqbar.project.wollok.codeGenerator.model.Context
import org.uqbar.project.wollok.wollokDsl.impl.WThrowImpl

import static extension org.uqbar.project.wollok.codeGenerator.ModelExtensions.*
import org.uqbar.project.wollok.wollokDsl.WAssignment
import org.uqbar.project.wollok.codeGenerator.model.Assignment
import static extension org.uqbar.project.wollok.model.WollokModelExtensions.*
import org.uqbar.project.wollok.codeGenerator.model.NativeMethod

class CodeAnalyzer {
val rootContext = new Program
val program = new Program(this)
var WFile wfile

def dispatch Expression analyze(WProgram program, Expression parent) {
program.eContents.forEach [
rootContext.operations.add(it.analyze(rootContext))
def dispatch Expression analyze(WProgram wprogram, Expression parent) {
wprogram.eContents.forEach [
program.operations.add(it.analyze(program))
]
rootContext
program
}

def dispatch Expression analyze(EObject o, Expression parent) {
Expand All @@ -44,9 +60,9 @@ class CodeAnalyzer {

def dispatch Expression analyze(WNumberLiteral o, Expression parent) { new NumberLiteral(parent, o.value) }

def dispatch Expression analyze(WNamedObject o, Context parent){
def dispatch Expression analyze(WNamedObject o, Program parent){
new NamedObject(o.name, parent) => [
o.members.forEach[ e | e.analyze(it) ]
o.members.forEach[ e | e.analyze(it.classDefinition) ]
parent.putVariableNamed(o.name, new Variable(parent, o.name) =>[ v | v.initialValue = it ])
]
}
Expand Down Expand Up @@ -85,12 +101,26 @@ class CodeAnalyzer {
]
}

def dispatch Expression analyze(WMethodDeclaration m, NamedObject parent){
new Method(parent) => [
it.operations.addAll(m.parameters.map[ e | e.analyze(it)])
m.expression.analyze(it)
parent.putMethodNamed(m.name, it)
]
def dispatch Expression analyze(WMethodDeclaration m, ClassDefinition classDefinition){
if(!m.native){
new Method(classDefinition) => [
m.parameters.map[ e | e.analyze(it)]
it.operations.addAll(m.expression.analyze(it))
classDefinition.putMethodNamed(m.name, it)
]
}else{
new NativeMethod(classDefinition, m.name, m.parameters.size) => [
classDefinition.putMethodNamed(m.name, it)
]
}
}

def dispatch Expression analyze(WParameter param, Method m){
new Parameter(param.name, m) => [ m.addParameter(it) ]
}

def dispatch Expression analyze(WSelf s, Expression parent){
new Self(parent)
}

def dispatch Expression analyze(WAssignment wa, Expression parent){
Expand All @@ -106,10 +136,58 @@ class CodeAnalyzer {
parent
}

def dispatch Expression analyze(WClass c, Program parent){
val className = c.fqn
var ClassDefinition superClass

if(className == "wollok.lang.Object")
superClass = null
else if(c.parent == null){
superClass = program.resolveWollokClass("wollok.lang.Object")
}else{
superClass = program.resolveWollokClass(c.parent.fqn)
}

new ClassDefinition(parent, className, superClass) => [
c.members.forEach[ e | e.analyze(it)]
]
}

def dispatch Expression analyze(WUnaryOperation op, Expression parent){
new MessageSend(parent) => [ ms |
ms.receiver = op.operand.analyze(ms)
ms.selector = op.feature
ms.parameters = #[]
]
}

def dispatch Expression analyze(WConstructorCall cc, Expression parent){
new ConstructorCall(parent) => [
]
}

def dispatch Expression analyze(WIfExpression ifExpr, Expression parent){
new IfExpression(parent)
}

def dispatch Expression analyze(WStringLiteral lit, Expression parent){
new StringLiteral(lit.value, parent)
}

def dispatch Expression analyze(WThrowImpl throwExp, Expression parent){
new ThrowExpression(parent)
}

def performAnalysis(WFile file) {
file.elements.forEach[it.analyze(rootContext)]
file.main.analyze(rootContext)
rootContext
this.wfile = file
wfile.elements.forEach[it.analyze(program)]
wfile.main.analyze(program)
program
}

def tryToResolve(String name) {
val wClass = WollokClassFinder.instance.getCachedClass(wfile, name)
wClass.analyze(program) as ClassDefinition
}

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package org.uqbar.project.wollok.codeGenerator

import org.uqbar.project.wollok.codeGenerator.model.Context
import org.uqbar.project.wollok.codeGenerator.model.Expression
import org.uqbar.project.wollok.codeGenerator.model.MethodContext

class ModelExtensions {
static def dispatch Context findContext(Expression expression){
static def dispatch MethodContext findContext(Expression expression){
expression.parent.findContext
}

static def dispatch Context findContext(Context context){
static def dispatch MethodContext findContext(MethodContext context){
context
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.uqbar.project.wollok.codeGenerator

import org.eclipse.xtend.lib.annotations.Accessors
import org.uqbar.project.wollok.codeGenerator.model.Expression
import org.uqbar.project.wollok.codeGenerator.model.types.context.TypeContext
import org.uqbar.project.wollok.codeGenerator.model.types.StringType

@Accessors
class StringLiteral implements Expression {
val String value
val Expression parent

new(String value, Expression parent){
this.value = value
this.parent = parent
}

override typeFor(TypeContext tc) {
new StringType
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.uqbar.project.wollok.codeGenerator

import org.eclipse.xtend.lib.annotations.Accessors
import org.uqbar.project.wollok.codeGenerator.model.Expression
import org.uqbar.project.wollok.codeGenerator.model.types.context.TypeContext

@Accessors
class ThrowExpression implements Expression {
val Expression parent
new(Expression parent){
this.parent = parent
}

override typeFor(TypeContext tc) {
throw new UnsupportedOperationException("TODO: auto-generated method stub")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.uqbar.project.wollok.codeGenerator.model

import org.eclipse.xtend.lib.annotations.Accessors
import org.uqbar.project.wollok.codeGenerator.model.types.context.TypeContext

@Accessors
class ClassDefinition extends AbstractMethodContext {

val Program parent
val String name
val ClassDefinition superClass

val methods = <String,Method>newHashMap

new(Program parent, String name, ClassDefinition superClass){
this.parent = parent
this.name = name
this.superClass = superClass
}

override typeFor(TypeContext tc) {
throw new UnsupportedOperationException("TODO: auto-generated method stub")
}

def Method getMethodNamed(String name) {
if(methods.containsKey(name)){
return methods.get(name)
}

if(superClass != null)
superClass.getMethodNamed(name)
else
throw new RuntimeException("Unknown method:" + name)
}

def putMethodNamed(String name, Method method) {
methods.put(name, method)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.uqbar.project.wollok.codeGenerator.model

import org.eclipse.xtend.lib.annotations.Accessors
import org.uqbar.project.wollok.codeGenerator.model.types.context.TypeContext

@Accessors
class ConstructorCall implements Expression {
val Expression parent

new(Expression parent){
this.parent = parent
}

override typeFor(TypeContext tc) {
throw new UnsupportedOperationException("TODO: auto-generated method stub")
}

}
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
package org.uqbar.project.wollok.codeGenerator.model

import org.uqbar.project.wollok.codeGenerator.model.types.context.TypeContext
import org.eclipse.xtend.lib.annotations.Accessors
import org.uqbar.project.wollok.codeGenerator.model.types.Type
import org.uqbar.project.wollok.codeGenerator.model.types.context.TypeContext

interface Context extends Expression {
def Variable getReturnVariable()

def Variable getVariableNamed(String name)

def boolean hasVariable(String name)

def void putVariableNamed(String name, Variable v)
}

@Accessors
abstract class AbstractMethodContext implements Context {
abstract class AbstractContext implements Context{
val variables = <String, Variable>newLinkedHashMap()
val operations = <Expression>newArrayList();
val returnVariable = new Variable(this, "_return");

override typeFor(TypeContext tc) {
returnVariable.typeFor(tc)
}

override getParent() {
parent
}


override getVariableNamed(String name) {
if (!this.hasVariable(name)) {
throw new RuntimeException("Unknown Variable:" + name)
Expand All @@ -41,5 +28,18 @@ abstract class AbstractMethodContext implements Context {
override hasVariable(String name) {
variables.containsKey(name)
}
}

interface MethodContext extends Context {
def Variable getReturnVariable()
}

@Accessors
abstract class AbstractMethodContext extends AbstractContext implements MethodContext {
val operations = <Expression>newArrayList();
val returnVariable = new Variable(this, "_return");

override typeFor(TypeContext tc) {
returnVariable.typeFor(tc)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.uqbar.project.wollok.codeGenerator.model

import org.eclipse.xtend.lib.annotations.Accessors
import org.uqbar.project.wollok.codeGenerator.model.types.context.TypeContext

@Accessors
class IfExpression implements Expression {
val Expression parent
new(Expression parent){
this.parent = parent
}

override typeFor(TypeContext tc) {
throw new UnsupportedOperationException("TODO: auto-generated method stub")
}

}
Loading

0 comments on commit 3fc6d45

Please sign in to comment.