Lab 2: Utility classes for an interpreter January 15, 2015

advertisement
Lab 2: Utility classes for an interpreter
January 15, 2015
The goal of this lab is for you to develop a few classes that will be usefull when
implementing the tree interpreter in Lab 3.
For each of the class, you are given a prototype, a test suite and a command to
run to check if your implementation is successfull.
1
The espy interpreter
1.1
Get the code
This is the first lab developing the espy interpreter. To conveniently run the test
suites on the university computer you should run the following commands:
1
2
module add /home/TDDA69/modulefiles/tdda69
module initadd /home/TDDA69/modulefiles/tdda69
The base code used in the labs is in the directory /home/TDDA69/Labs. To get
the code and start working on it, in your home directory:
1
cp -r /home/TDDA69/Labs/espy $HOME
This will copy the skeleton for the espy interpreter, you can now find it in the
directory $HOME/espy. In the rest of the document and in other lab, we will refer
to this directory as dir to espy.
1.2
Code base structure
If you look at the code base for the espy interpreter, you will see the following files
and directory:
• es.py this is the main executable of your interpreter, it is run with the following
command:
1
./es.py [file.js]
• ECMAScriptParser this the code of the parser that was generated by antrl4
• antrl4 this is the runtime library used by the parser
• Utils this is a directory with usefull classes and functions. You should have a
look at it to see what is available
• Interpreter this is the directory where you will do most of your work, it should
contains skeleton classes that you will need to implement during the labs.
1
For this lab, your focus should be on the followig files in the Interpreter class:
• Environment.py skeleton class for an environment for the interpreter
• Function.py skeleton class to represent ECMAScript function
• Property skeleton class to represent the property of an ECMAScript object
In /home/TDDA69/Labs/Lab2/Tests, you will find the source code for the unit
tests corresponding to each of the class that should be implementing during this lab.
2
Environment
The purpose of this class is to handle the variable. This class contains functions for
defining a variable, setting its value and accessing the value.
2.1
1
2
3
4
5
6
7
8
9
10
Interface
class Environment:
"""
Environment class used to define variables.
"""
def __init__(self, parent = None):
"""
Initialise an environment. The parent is an other environment
where value for variables can be looked up recursively.
"""
pass
11
12
13
14
15
16
17
def defineVariable(self, name, init = None):
"""
Create a new variable with the name "name" and the initial value
"init".
"""
pass
18
19
20
21
22
23
24
25
26
def setVariable(self, name, value):
"""
Set the value of a variable. If the variable is not defined in
this environment, it should look in the parent environment.
If it is not found in the root environment, it should raise the
exception Utils.UnknownVariable.
"""
pass
27
28
29
30
31
32
33
34
def value(self, name):
"""
Get the value of a variable. If the variable is not defined in
this environment, it should look in the parent environment.
If it is not found in the root environment, it should raise the
exception Utils.UnknownVariable.
"""
2
pass
35
2.2
Run the test
tdda69_lab2_tests dir_to_espy environment
1
3
Function
This class is intended to help executing functions in the interpreter.
3.1
1
Interface
from Interpreter.Environment import Environment
2
3
4
5
6
class Function:
’’’
This class represent a JavaScript function. It is a callable python
object.
7
8
9
10
11
It can be used like this:
f = Function(["arg1", "arg2"], Environment(),
lambda env: print(env.value("arg1") + env.value("arg2")))
f(1,2)
12
13
And it should print 3.
14
15
16
17
18
19
An other example of use would be:
f = Function(["arg1", "arg2"], Environment(),
lambda env: raise ControlExceptions.ReturnException(
print(env.value("arg1") + env.value("arg2"))))
print(f(1,2))
20
21
And it should also print 3.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
’’’
def __init__(self, args, environment, body):
’’’
This creates a new function with a set of args (which is an array
of string with the name of the variables used as arguments), the
global environment used when defining the function and a lambda
function defining the body to be called (should take one single
argument, which is the environment)
’’’
pass
def call(self, that, this, *args):
’’’
Call the function. This function is usefull since in ECMAScript,
a function is an object and it can be called with the function
"call". For instance:
38
3
function MyFunction(arg)
{
console.log(arg)
}
MyFunction.call(2)
39
40
41
42
43
44
In which case, that is a pointer to MyFunction and this to None.
But where it becomes tricky is with:
45
46
47
var obj = { member: function(arg) { this.value = arg } }
obj.call(2)
48
49
50
In which case that contains obj.member and this contains obj.
51
52
In practice, the that argument can be ignored.
53
54
In other word:
* that is the pointer to the object of the function
* this is the pointer to the object (equivalent of self in
python)
* args is the list of arguments passed to the function
’’’
pass
def __call__(self, this, *args):
’’’
Call the function. With the this argument.
’’’
pass
55
56
57
58
59
60
61
62
63
64
65
66
3.2
Run the test
tdda69_lab2_tests dir_to_espy function
1
4
Property
In ECMAScript it is possible to define properties to an object that are actually
calling a function. For instance:
var obj = { val: 2,
get value: function() { return this.val + 1; },
set value: function(v) { this.val = v - 1 } }
obj.value = 4
console.log(obj.val)
console.log(obj.value)
1
2
3
4
5
6
Will show
4.1
Interface
To support this feature in your interpreter, we suggest to use the following class:
4
1
import Utils
2
3
4
5
6
7
8
class ReadOnlyException(Exception):
’’’
Exception thrown when accessing a read only property
’’’
def __init__(self):
pass
9
10
11
12
13
14
15
class WriteOnlyException(Exception):
’’’
Exception thrown when accessing a write only property
’’’
def __init__(self):
pass
16
17
18
19
20
21
22
23
24
25
26
class Property:
’’’
Define an ECMAScript style property. This should contains three
members:
* getter a Function that is called when accessing the value
* setter a Function that is called when setting the value
* this the object to which this property belongs
’’’
def __init__(self):
pass
27
28
29
30
31
32
def get(self):
’’’
Get the value or raise WriteOnlyException
’’’
pass
33
34
35
36
37
38
def set(self, value):
’’’
Set the value or raise ReadOnlyException
’’’
pass
39
40
41
42
43
44
45
46
47
48
49
def merge(self, other):
’’’
Merge two properties.
’’’
pass
def clone(self):
’’’
Clone a property (useful when creating new objects).
’’’
pass
5
4.2
Run the test
tdda69_lab2_tests dir_to_espy property
1
5
Submit your code
Before submiting your code to the lab assistant, check that all the tests are working
properly:
1
tdda69_lab2_tests dir_to_espy
6
Download