플젝3 체크리스트
Closed this issue · 7 comments
zzJinux commented
- symbol table creation
- 선언되지 않은 변수나 함수는 사용 불가
- 변수나 함수, 함수 파라미터 선언 시 중복된 이름 check
- 변수나 parameter 선언 시 void type으로 선언할 수 없음
- 변수나 parameter 선언 시 array type 확인
- scoping error check
- type error check
- operand type check (l-value, assignment, array subscripting)
-
a = b: isalvalue?, 양변 타입 일치 -
a[b]: isaarray?, isbinteger? -
a(b, c): isafunction?
-
- while/if statement condition type
- operand type check (l-value, assignment, array subscripting)
- function call check
- 함수 호출 시 parameter의 개수와 type이 일치하는지 check
- 함수의 return 값과 return type이 일치하는지 check
- 함수의 return type이 void일 경우 return statement 자체가 없음 (?)
- main함수는 가장 마지막에 선언되어야 함
- main함수는 반드시 void로 선언되어야 함
- main함수는 반드시 parameter가 존재하지 않는다.
zzJinux commented
edited
zzJinux commented
- stack offset 계산 모호함
- 시작주소는 0부터? -4 부터?
- 내가 내린 결정: -4 (lower address)
- global variable memory offset 계산 모호함
- lower address? upper address?
- 내가 내린 결정: lower address
zzJinux commented
에러메시지 줄번호
zzJinux commented
zero-sized array(variable declaration) ?
-> emit error!
zzJinux commented
<global context> {
an AST: TreeNode *
a list of scopes (ref. AST): Scope *
a stack of scopes of upper blocks (w/ size counter): Scope *
a flag for handling the function body block presence (function flag): int
# if set, indicates that you are analyzing a function
a flag for "main function" declaration ("main" flag): int
# if set, indicates that you are in the middle of, or done with analyzing the main function
scope id counter: int
function loc counter: int
}
struct Scope {
scope id: int
stack counter: int
symbol table: BucketList *
}
((added attributes))
struct TreeNode {
Scope ref (for compount stmt)
}
func buildSymtab(TreeNode *tnode):
initialize:
[a list of scope] := empty list
[a stack of scopes of upper blocks] := empty stack
[a flag for handling the function body block presence] := 0
[a flag for "main function" declaration ("main" flag)] := 0
[scope id counter] := 0
[function loc counter] := 0
enterScope()
[current scope stack counter] := 0
# static variable loc counter
traverse(tnode, pre, post)
exitScope()
if "main" flag is clear
error(MAIN_FUNCTION_NOT_EXISTS)
func buildSymtab_pre(TreeNode *tnode):
######## WORKING WITH SCOPES #########
if TNODE is of a compound statement(block):
if function flag is set:
unmark it
else:
enterScope()
set the current scope's stack counter to -4 (pointer width)
elif TNODE is of a function declaration:
if "main" flag is set:
error(MAIN_FUNCTION_MUST_APPEAR_LAST)
mark the function flag
enterScope()
set the current scope's stack counter to 4 (pointer width)
if it's the main function:
if its parameter is not void
error(MAIN_FUNCTION_PAARM_TYPE_IS_NON_VOID)
if its return type is not void:
error(MAIN_FUNCTION_RETURN_TYPE_IS_NON_VOID)
mark the "main" flag
######## INSERT SYMBOLS #########
if TNODE is of a var/func declaration or parameter
get the name of it
if the name is already present in the current scope:
error(REDIFINITION)
if it's a function decl:
insert new symbol (function, loc = [function loc counter])
++[function loc counter]
elif: # a variable decl:
if the type is void:
error(VARIABLE_HAS_INCOMPLETE_TYPE)
# how to check if we are in global scope?
# just check if current scope id!
if not global scope
# check array
[stack counter of current scope] -= 4 * sz (int width)
insert new symbol (variable, loc = [stack counter])
else:
insert new symbol (variable, loc = [stack counter])
[stack counter of current scope] += 4 * sz (int width)
else: # TNODE is of a parameter
if the parameter does not exist (null param):
skip current function
if the type is void:
error(PARAMETER_HAS_INCOMPLETE_TYPE)
# check array
insert new symbol (parameter, loc = [stack counter])
[current stack counter] += 4 (int width)
void buildSymtab_post (TreeNode *tnode)
if TNODE is of a compound statement(block):
exitScope()
elif TNODE is of a var-expression/call-expression
lookup the name on the whole stack of scopes
if found:
add a line number to the lineList of the symbol record
else:
error(IDENTIFIER_NOT_FOUND)
enterScope(void):
create a scope for the function
push the scope
append the scope (to list)
exitScope(void):
store the scope object to current ast node
pop the scope
void typeCheck(TreeNode *tnode)
// TODO
HaebinShin commented
<global context> {
an AST: TreeNode *
a list of scopes (ref. AST): Scope *
a stack of scopes of upper blocks (w/ size counter): Scope *
a flag for handling the function body block presence (function flag): int
# if set, indicates that you are analyzing a function
a flag for "main function" declaration ("main" flag): int
# if set, indicates that you are in the middle of, or done with analyzing the main function
scope id counter: int
function loc counter: int
}
struct Scope {
scope id: int
stack counter: int
symbol table: BucketList *
}
((added attributes))
struct TreeNode {
Scope ref (for compount stmt)
}
func buildSymtab(TreeNode *tnode):
initialize:
[a list of scope] := empty list
[a stack of scopes of upper blocks] := empty stack
[a flag for handling the function body block presence] := 0
[a flag for "main function" declaration ("main" flag)] := 0
[scope id counter] := 0
[function loc counter] := 0
enterScope()
traverse(tnode, pre, post)
exitScope()
if "main" flag is clear
error(MAIN_FUNCTION_NOT_EXISTS)
func buildSymtab_pre(TreeNode *tnode):
if TNODE is of a compound statement(block):
if function flag is set:
unmark it
else:
enterScope()
set the current scope's stack counter to -4 (pointer width)
elif TNODE is of a function declaration:
if "main" flag is set:
error(MAIN_FUNCTION_MUST_APPEAR_LAST)
mark the function flag
enterScope()
set the current scope's stack counter to 4 (pointer width)
if it's the main function:
if its parameter is not void
error(MAIN_FUNCTION_PAARM_TYPE_IS_NON_VOID)
if its return type is not void:
error(MAIN_FUNCTION_RETURN_TYPE_IS_NON_VOID)
mark the "main" flag
void buildSymtab_post (TreeNode *tnode)
if TNODE is of a compound statement(block):
exitScope()
elif TNODE is of a var/func declaration or parameter
get the name of it
if the name is already present in the current scope:
error(REDIFINITION)
if it's a function decl:
insert new symbol (function, loc = [function loc counter])
++[function loc counter]
elif: # a variable decl:
if the type is void:
error(VARIABLE_HAS_INCOMPLETE_TYPE)
# check array
[stack counter of current scope] -= 4 (int width)
insert new symbol (variable, loc = [stack counter])
else: # TNODE is of a parameter
if the parameter does not exist (null param):
skip current function
if the type is void:
error(PARAMETER_HAS_INCOMPLETE_TYPE)
# check array
insert new symbol (parameter, loc = [stack counter])
[current stack counter] += 4 (int width)
elif TNODE is of a var-expression/call-expression
lookup the name on the whole stack of scopes
if found:
add a line number to the lineList of the symbol record
else:
error(IDENTIFIER_NOT_FOUND)
enterScope(void):
create a scope for the function
push the scope
append the scope (to list)
exitScope(void):
store the scope object to current ast node
pop the scope
void typeCheck_pre(TreeNode *tnode) {
if StmtK:
if CompdK:
scope_push()
}
void typeCheck_post(TreeNode *tnode) {
if ExprK:
if opExprK:
if array:
if index is not integer:
error()
else if ASSIGN:
if tnode->child[0] == void:
error()
else if lhs is array and k is VOID:
error()
//if tnode->child[0]==array:
// typeError(“array cannot assign”)
else if tnode->child[1]==void:
typeError(“cannot assign void variable”)
else:
tnode->type = tnode->child[1]->type
else:
left = tnode->child[0]
right = tnode->child[1]
if left is void or right is void:
typeError()
// TODO (anything else?)
else
tnode->type = int;
else if constK:
tnode->type = int;
else if varK:
sym = st_lookup()
if !sym
error(undefined var)
tnode->type = sym->type;
else if callK:
sym = st_lookup()
if !sym
error(undefined func)
if sym is not func:
error()
declParam = sym->child[]
nowParam = tnode->child[]
while(nowParam) {
if !declParam
error(“argument count not same”)
if nowParam is void type:
error()
else{
nowParam = nowParam->sibling;
declParam = declParam->sibling;
}
}
if declParam
error(“argument count not same”)
else if StmtK:
if CompdK:
scope_pop()
else if SelectK:
if tnode->child[0] is void:
error()
else if IterK:
if tnode->child[0] is void:
error()
else if RetK:
funcSym = st_lookup()
if tnode->nChildren > 0 && tnode->child[0] != void:
nowType = int;
else:
nowType = void;
if funcSym->type != nowType:
error()
}
void typeCheck(TreeNode *tnode)
// TODO
enterScope()
traverse(tnode, pre, post)
exitScope()zzJinux commented
void returning void function
void vovovo() {}
void func() {
return vovovo();
}
int main() {
func();
return 0;
}