CS252-Slides-2015-to..
Download
Report
Transcript CS252-Slides-2015-to..
CS252
Lab 2
Prepared by El Kindi Rezig
Notes
• Check out new version of the “official” fiz
interpreter at
•
•
https://www.cs.purdue.edu/homes/ninghui/courses/252_Spri
ng15/code/fizlab/fiz
New functionality: tracing
Use “help” in the interpreter
fiz> help
You can use the following commands:
import <file_name>
tracing on
tracing off
(define (<func_name> <<arg_list>>) <<expr>>)
<<expr>>
The grammar for <<expr>> is:
<<expr>> ::= (inc <<expr>>)
| (dec <<expr>>)
| (ifz <<expr>> <<expr>> <<expr>>)
| (halt)
| (<func_name> <<expr_list>>)
Result of tracing (for add)
fiz> tracing on
fiz> (add 3 2)
Evaluating (add 3 2)
Evaluating (ifz 2 3 (add (inc ..) (dec ..)))
Evaluating (add 4 1)
Evaluating (ifz 1 4 (add (inc ..) (dec ..)))
Evaluating (add 5 0)
Evaluating (ifz 0 5 (add (inc ..) (dec ..)))
(add 5 0) = 5
(add 4 1) = 5
(add 3 2) = 5
5
Result of tracing (for sub)
fiz> (sub 3 2)
Evaluating (sub 3 2)
Evaluating (ifz 2 3 (ifz 3 (halt) (sub (dec ..) (dec ..))))
Evaluating (ifz 3 (halt) (sub (dec ..) (dec ..)))
Evaluating (sub 2 1)
Evaluating (ifz 1 2 (ifz 2 (halt) (sub (dec ..) (dec ..))))
Evaluating (ifz 2 (halt) (sub (dec ..) (dec ..)))
Evaluating (sub 1 0)
Evaluating (ifz 0 1 (ifz 1 (halt) (sub (dec ..) (dec ..))))
(sub 1 0) = 1
(sub 2 1) = 1
(sub 3 2) = 1
1
Notes
•
Try write some fiz programs using the interpreter
•
E.g., write (max x y z), which outputs the max value
among x,y,z.
•
Do it from the ground up
•
Will help you in the exam
Formal and Actual Arguments
•
•
•
•
Arguments are also known as parameters
Formal arguments/parameters appear in function
definition
Actual arguments/parameters appear in function calls
E.g.,
Formal
(define (add x y)
(ifz y x (add (inc x) (dec y))))
(add 3 2)
Actual
Overview
- Lab 2 has two parts:
1. FIZ without user-defined functions (50%):
Parse and evaluate built-in FIZ functions.
2. Support of user-defined functions’
declarations and calls (50%): Parse and
evaluate user-defined functions’ declarations
and calls.
Lab 2: Part 1 (FIZ without user-defined functions)
The language grammar:
<expression> : (inc <expression>) | (dec <expression>)
| (ifz <expression> <expression> <expression>)
| (halt) | NUMBER
All expressions evaluate to a non-negative integer value.
Lab 2: Part 1 (FIZ without user-defined functions)
Example statements that are supported by FIZ:
(inc (inc 5))
// interpreter prints 6
(dec (inc (dec 3)))
// interpreter prints 2
(dec (ifz 0 4 (inc 1)))
// interpreter prints 3
Example statements that are NOT supported by FIZ:
(inc 4 5) // Error: inc only takes 1 argument.
(ifz 0 halt) // Error: halt used without parenthesis, no else
statement
(inc (dec )) //Error: no argument for “dec”.
Lab 2: Part 1 (FIZ without user-defined functions)
TODO
- Implement the scanner and parser.
- For any newly added files, type:
-
1. git add {new file name}
2. git commit -am "description of the changes you have made."
3. git push
You need to push all your changes before: 02/09/2015, 11:59pm.
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
- Parse and evaluate user-defined functions’
declarations and calls.
- Add to the parser to parse the following:
1. (define (ID <arg>+) <expression> )
2. (ID <expression>+)
- Evaluate the user-defined declarations and
calls.
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
FUNC_DECL structure definition:
name
argNames
body
numArgs argNames
body
numArgs
Example: (define (foo x) (inc x))
name
FUNC_DECL
foo
Could be a size-10
array, with only the
first element used
TREE_NODE
1
x
INC
ARG_NAME
NODE TYPE
x
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
Example: (define (add x y) (ifz y x (add (inc x) (dec y))))
numArgs
FUNC_DECL
add
argNames
body
ARG_NAME
ARG_NAME
y
2
x
y
IFZ
numArgs
name
Could be a size-10
array, with only the
first two elements used
x
FUNC_CALL
add
2
NODE TYPE
INC
ARG_NAME
x
DEC
ARG_NAME
y
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
Example: (add (inc 1) 2)
name
FUNC_CALL
numArgs
add
INC
NUMBER_NODE
args
1. Resolve expression
2
NUMBER_NODE
1
2
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
Example: (add (inc 1) 2)
FUNC_EVAL
Add
reference to
the function
declaration
structure
args
numArgs
func
1. Resolve expression
2
INC
NUMBER_NODE
NUMBER_NOD
E
FUNC_DECL
add
2
1
ARG_NAME
x
ARG_NAME
y
2
x
y
IFZ
y
FUNC_CALL
x
2
add
DEC
INC
ARG_NAME
x
ARG_NAME
y
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
Example: (add (inc 1) 2)
args
numArgs
func
FUNC_EVAL
1. Resolve expression
2
2.
Add
reference to
the function
declaration
structure
INC
NUMBER_NODE
NUMBER_NOD
E
FUNC_DECL
add
Evaluate parameters
2
1
ARG_NAME
x
ARG_NAME
y
2
x
y
IFZ
y
FUNC_CALL
x
2
add
DEC
INC
ARG_NAME
x
ARG_NAME
y
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
Example: (add (inc 1) 2)
numArgs
func
FUNC_EVAL
args
1. Resolve expression
2. Evaluate parameters
2
INC
NUMBER_NODE
NUMBER_NOD
E
2
FUNC_DECL
add
2
1
ARG_NAME
x
ARG_NAME
y
2
x
y
IFZ
y
FUNC_CALL
x
2
add
DEC
INC
ARG_NAME
x
ARG_NAME
y
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
Example: (add (inc 1) 2)
numArgs
func
FUNC_EVAL
args
1. Resolve expression
2. Evaluate parameters
2
INC
NUMBER_NODE
2
2
NUMBER_NOD
E
2
FUNC_DECL
add
1
ARG_NAME
x
ARG_NAME
y
2
x
y
IFZ
y
FUNC_CALL
x
2
add
DEC
INC
ARG_NAME
x
ARG_NAME
y
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
1. Resolve expression
2. Evaluate parameters
3. Resolve body of add
NUMBER_NOD
E
FUNC_DECL
add
1
ARG_NAME
x
ARG_NAME
y
2
x
y
IFZ
y
x
2
FUNC_EVAL
DEC
INC
ARG_NAME
x
ARG_NAME
y
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
NUMBER_NOD
E
FUNC_DECL
add
1
ARG_NAME
x
ARG_NAME
2
x
y
IFZ
y
x
2
FUNC_EVAL
DEC
INC
ARG_NAME
1.
2.
3.
4.
Resolve expression
Evaluate parameters
Resolve body of add
Pass computed
params to the
function.
y
x
ARG_NAME
y
Lab 2: (support of user-defined functions’ declaration
and calls) (50%)
TODO for this part
1. Add the (define) construct into the grammar.
2. Function declaration: Build the AST for each userdefined function and store it.
3. Function call: Lookup the AST of the called function,
and evaluate its branches using the provided parameters.
4. You need to push all your changes before: 02/16/2015,
11:59pm.
Where to Add Your Code in fiz.y?
%token INC OPENPAR CLOSEPAR
// more tokens
%type <node_val> expr
// more non-terminals
enum NODE_TYPE{
INC_NODE,
NUMBER_NODE,
// more node types
};
struct TREE_NODE{
enum NODE_TYPE type;
union {
struct TREE_NODE *first_arg;
int
intValue;
// more union members for other node types
};
};
Union in C
union {
struct TREE_NODE *first_arg;
int
intValue;
// more union members for other node types
// such as struct { … } field;
};
A union stores different data types in the same memory
location
In the union above, first_arg and intValue refer to the same
memory location, as is any other additional member in the union. The
size of a union is the max of the size of all its components.
A union member can be a struct as well.
Why Use Union
Reason 1: Want to access the same data in different ways, e.g., an IP
address, or a hardware register can be defined as
union {
struct {
unsigned char byte1;
unsigned char byte3;
} bytes;
unsigned int word;
} HW_Register;
reg.dword = 0x12345678;
reg.bytes.byte3 = 4;
unsigned char byte2;
unsigned char byte4;
Similarly, using a union for an IP address allows access individual
bytes in the address as well as treating them as integer
Why Use Union
Reason 2: Implement pseudo-polymorphism. A structure may include
different types of data (e.g., a TREE_NODE in FIZ interpreter may be
of several different types).
A field, type, indicates which type of node this is.
The union includes the actual data needed for this type of node.
Typically, assigning value to and retrieving from the node should use
the same union member.
See code for example.
Where to Add Your Code in fiz.y?
struct FUNC_DECL {
char *name;
// Other information of the function needs to be added
};
// More grammar rules
statement: OPENPAR DEFINE OPENPAR …
// define a function
expr: …
// handle function call
// auxiliary rules that may be needed to define the above two
Where to Add Your Code in fiz.y?
void resolve (struct TREE_NODE *node, struct FUNC_DECL *cf){
// cf==NULL when resolving an expression as a statement
// cf points to the function when resolving a function
// body
switch(node->type) {
// Add code to resolve appearances of function names, and
// usage of arguments if we are resolving the body of a
// function
}
return;
}
Where to Add Your Code in fiz.y?
int eval(struct TREE_NODE * node, int *env){
// env=NULL when evaluating an expression as a statement
// env points to an array of actual arguments when evaluating the
// body of a function
switch(node->type) {
case NUMBER_NODE:
return node->intValue;
case INC_NODE:
return eval(node->first_arg, env) + 1;
// Add code to evaluate other kinds of expressions, especially
// a function call, for which we need to evaluate the actual
// arguments first, and then evaluate the body, passing in the
// array of actual argument values
}
}
Avoiding Buffer Overflow and
Memory Leak
• Count as 10% extra credit for Lab 2.
• Avoid buffer overflow: avoid using fixed-size
buffer for identifiers
• Avoid memory leak: Free allocated memory
when no longer needed
•
•
•
An expression statement after evaluated
Define statement when there is an error in functional
definition
Possibly other things