## [CS143-PA3] Semantic Analyzer

full file link https://github.com/Aria461863631/cs143/tree/master/PA4

used files

• semant.c: write semantic analysis in semant() function
• semant.h: header file
• cool-tree.h or cool-tree.handcode.h: add additional declarations
• symtab_example.cc: example for using SymbolTable

### Inheritance

start implementing ClassTable for representing the inheritance graph.

requirements

• All class names are globally visible.

• inheritance graph be acyclic

• basic classes
It is an error to inherit from or redefine Int, Str, Bool.
It is an error to redefine the IO class.
A class can make use of the methods in the IO class by inheriting from IO.
• It is also an error if class A inherits from class B but class B is not defined.

### Naming and Scoping

The type environment consists of three parts:

• the name of the current class $C$

• an object environment $O$ is a function of the form $$O(v) = T$$which assigns the type $T$ to object identifier $v$.

• a method environment $M$ it is a function of the form $$M (C, f ) = (T_1 , . . . , T _{n−1} , T _n )$$

• $C$ is a class name (a type), $f$ is a method name, and $t_1 , . . . , t_n$ are types.
• The tuple of types is the signature of the method.
• The interpretation of signatures is that
in class $C$ the method $f$ has formal parameters of types $(t_1 , . . . , t_{n−1} )$—in that order—and a return type $t_n$

using symbol table to represent type environment

install symbol tables

In Cool all attributes have scope local to the class, and all methods have global scope.

first install global method table

then install object table

### Type Checking

implemented in a single traversal over AST

type environment is passed down the tree: from parent to child

types are passed up the tree: from child to parent

method

attribute

### Code Generator Interface

For every expression node, its type field must be set to the Symbol naming the type inferred by your type checker.

static vs dynamic

The dynamic type of an object is the class $C$ that is used in the new C expression that created it

Soundness theorem for Cool type system;

$\forall E, dynamic\_type(E) \le static\_type(E)$

all operations that can be used on an object of type $C$ can also be used on an object of type $C^{‘} \le C$

static-dispatch

if

case

• Case expressions provide runtime type tests on objects.
• First, $e_0$ is evaluated and its dynamic type C noted.
• Next, from among the branches the branch with the least type $T_k$ such that $C ≤ T_k$ is selected. The identifier $x_k$ is bound to the value of $e_0$ and the expression $e_k$ is evaluated.
• The result of the case is the value of $e_k$

let-init

• Typing a multiple let
let $x_1 : T_1 [← e_1 ], x_2 : T_2 [← e_2], . . . , x_n : T_n [← e_n ]$ in $e$
is defined to be the same as typing
let $x_1 : T_1 [← e_1 ]$ in (let_expr…)

new

var

### SELF_TYPE

The type SELF_TYPE is used to refer to the type of the self variable.

Note that the meaning of SELF_TYPE is not fixed, but depends on the class in which it is used.

• $SELF\_TYPE_C$ to refers to an occurrence of SELF_TYPE in the body of C

cannot return self with a concrete type

inheritance rule

Let $T$ and $T^{‘}$ be any types but SELF_TYPE

$SELF\_TYPE_C \le SELF\_TYPE_C$

• In Cool we never compare SELF_TYPE coming from different classes

$SELF\_TYPE_C \le T$ if $C \le T$

• $SELF\_TYPE_C$ can be any subtype of C, including C itself

$T \le SELF\_TYPE_C$ always false

least upper bound rule

lub($SELF\_TYPE_C$, $SELF\_TYPE_C$) = $SELF\_TYPE_C$

lub($SELF\_TYPE_C$,$T$) = lub($C$, $T$)

lub($T$,$SELF\_TYPE_C$) = lub($C$, $T$)

Finally, SELF TYPE may be used in the following places:

• new SELF_TYPE

• the return type of a method

• the declared type of a let variable

• the declared type of an attribute.

• actual arguments of methods ( ≤ declared arguments type )

• type of dispatch expression

No other uses of SELF_TYPE are permitted.

• classname

• static dispatch

• formal parameters

functions