summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parser.fun174
1 files changed, 139 insertions, 35 deletions
diff --git a/parser.fun b/parser.fun
index ecaab22..caa755f 100644
--- a/parser.fun
+++ b/parser.fun
@@ -157,7 +157,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
StmtFor of exprAug option * exprAug option * exprAug option * stmt |
StmtWhile of exprAug * stmt |
StmtDoWhile of stmt * exprAug |
- StmtReturn of exprAug |
+ StmtReturn of exprAug option |
StmtBreak |
StmtContinue
@@ -192,8 +192,9 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
datatype ctx = Ctx of {
localScopes: scope list,
-
localVars: (int * P.tkPos * ctype) list,
+ funcRetType: ctype option,
+
globalDecls: (int, P.tkPos * declClass * ctype * linkage) Tree.t,
tokenBuf: P.t * (token * P.tkPos) list list,
@@ -207,12 +208,16 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
fun updateCtx (Ctx ctx) = fn z =>
let
- fun from localScopes localVars globalDecls tokenBuf loopLevel =
- { localScopes, localVars, globalDecls, tokenBuf, loopLevel }
- fun to f { localScopes, localVars, globalDecls, tokenBuf, loopLevel } =
- f localScopes localVars globalDecls tokenBuf loopLevel
+ fun from localScopes localVars funcRetType globalDecls
+ tokenBuf loopLevel =
+ { localScopes, localVars, funcRetType, globalDecls,
+ tokenBuf, loopLevel }
+
+ fun to f { localScopes, localVars, funcRetType, globalDecls,
+ tokenBuf, loopLevel } =
+ f localScopes localVars funcRetType globalDecls tokenBuf loopLevel
in
- FRU.makeUpdate5 (from, from, to) ctx (fn (a, f) => z (a, Ctx o f))
+ FRU.makeUpdate6 (from, from, to) ctx (fn (a, f) => z (a, Ctx o f))
end
datatype declParts =
@@ -565,10 +570,24 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
function_t _ => true
| _ => false
+
val isPointer = fn
pointer_t _ => true
| _ => false
+ fun isObj (void_t | function_t _) = false
+ | isObj _ = true
+
+ fun isPointerToObj (pointer_t (n, t)) =
+ if n > 1 then
+ true
+ else
+ isObj t
+ | isPointerToObj _ = false
+
+ fun funcParts (function_t pair) = pair
+ | funcParts _ = raise Unreachable
+
val pointsTo = fn
pointer_t (1, t) => t
| pointer_t (n, t) =>
@@ -578,6 +597,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
fun createCtx fname incDirs = Ctx {
localScopes = [],
localVars = [],
+ funcRetType = NONE,
globalDecls = Tree.empty,
tokenBuf = (P.create { fname, incDirs, debugMode = false }, []),
loopLevel = 0
@@ -678,8 +698,10 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
fun ~s = Printf out `s %
in
case unop of
- UnopPreInc | UnopPostInc => ~"++"
- | UnopPreDec | UnopPostDec => ~"--"
+ UnopPreInc => ~"++@"
+ | UnopPostInc => ~"@++"
+ | UnopPreDec => ~"--@"
+ | UnopPostDec => ~"@--"
| UnopSizeof => ~"sizeof"
| UnopPos => ~"+"
| UnopNeg => ~"-"
@@ -836,6 +858,11 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
and parseFuncCall funcEa pos ctx =
let
+ fun isEmpty ctx =
+ case #1 $ getTokenCtx ctx of
+ Tk T.EOS => true
+ | _ => false
+
fun collectArgs acc ctx =
let
val ((status, ea), ctx) = parseExpr [T.Comma] ctx
@@ -845,7 +872,8 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
else
collectArgs (ea :: acc) ctx
end
- val (args, ctx) = collectArgs [] ctx
+
+ val (args, ctx) = if isEmpty ctx then ([], ctx) else collectArgs [] ctx
in
(SOME $ makeEA (EfuncCall (funcEa, args)) pos, ctx)
end
@@ -1243,6 +1271,8 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
and convEA t (E as EA (_, pos, _, t')) =
if t = t' then
E
+ else if t' = void_t then
+ P.error pos `"unable to convert void" %
else
EA (Eunop (UnopCast, E), pos, false, t)
@@ -1301,11 +1331,11 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
in
case unop of
UnopPostInc | UnopPostDec | UnopPreInc | UnopPreDec =>
- if isArith ot orelse isPointer ot then
+ if isScalar ot andalso isLvalue oper then
EA (Eunop (unop, oper), pos, true, ot)
else
P.error (getPos oper)
- `"expected an arithmetic or a pointer expression" %
+ `"expected an arithmetic or a pointer lvalue expression" %
| UnopPos | UnopNeg =>
if isArith ot then
toInt ()
@@ -1370,7 +1400,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
end
| justConvArith _ _ = raise Unreachable
- and checkRel (E as (EA (Ebinop (binop, left, right), _, _, _))) =
+ and checkRel (E as (EA (Ebinop (binop, left, right), pos, _, _))) =
let
val isEqCheck =
case binop of BR BrEqual | BR BrNotEqual => true | _ => false
@@ -1385,9 +1415,10 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
if isPointer rightT then
if pointsTo leftT = pointsTo rightT then
setT E int_t
- else if isEqCheck andalso (rightT = voidp orelse leftT = voidp)
- then
- setT E int_t
+ else if isEqCheck andalso rightT = voidp then
+ EA (Ebinop (binop, convEA voidp left, right), pos, false, int_t)
+ else if isEqCheck andalso leftT = voidp then
+ EA (Ebinop (binop, left, convEA voidp right), pos, false, int_t)
else
P.error rightPos `"pointer type does not match left sibling" %
else
@@ -1424,11 +1455,11 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
if isArith leftT then
if isArith rightT then
justConvArith E ResFromHigher
- else if isPointer rightT then
+ else if isPointerToObj rightT then
setT E rightT
else
P.error rightPos `"expeced pointer" %
- else if isPointer leftT then
+ else if isPointerToObj leftT then
if isIntegral rightT then
setT E leftT
else if isSub andalso isPointer rightT then
@@ -1508,9 +1539,9 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
val rightT = getT right
val (left, right) =
- if isPointer leftT andalso isIntegral rightT then
+ if isPointerToObj leftT andalso isIntegral rightT then
(left, convEA long_t right)
- else if isIntegral leftT andalso isPointer rightT then
+ else if isIntegral leftT andalso isPointerToObj rightT then
(right, convEA long_t left)
else
P.error pos `"expected pointer and integral pair" Pctype leftT %
@@ -1553,12 +1584,32 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
and checkFuncCall check (EA (EfuncCall (func, args), pos, _, _)) =
let
- (* TODO: check arguments *)
+ fun checkArg arg =
+ let
+ val arg = check arg
+ in
+ if isObj $ getT arg then
+ arg
+ else
+ P.error pos `"function argument is not of object type" %
+ end
+
val func = check func
+ val args = List.map checkArg args
+
+ fun convertArgs (t :: ts) (arg :: args) =
+ convEA t arg :: convertArgs ts args
+ | convertArgs [] [] = []
+ | convertArgs _ _ =
+ P.error pos `"function called with invalid number of arguments" %
in
case getT func of
- pointer_t (1, function_t (rt, _)) =>
+ pointer_t (1, function_t (rt, argTypes)) =>
+ let
+ val args = convertArgs argTypes args
+ in
EA (EfuncCall (func, args), pos, false, rt)
+ end
| _ => P.error pos `"expected pointer to function" %
end
| checkFuncCall _ _ = raise Unreachable
@@ -1584,16 +1635,21 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
in
EA (Eternary (cond, thenPart, elsePart), pos, false, resT)
end
+
else if thenT = void_t andalso elseT = void_t then
setT E void_t
+
else if isPointer thenT then
if thenT = elseT then
setT E thenT
- else if elseT = voidp orelse thenT = voidp then
+ else if elseT = voidp then
+ setT E voidp
+ else if isPointer elseT andalso thenT = voidp then
setT E voidp
else
P.error (getPos elsePart)
`"expression type is incompatible with its left sibling" %
+
else
P.error (getPos thenPart)
`"expected expression of pointer or arithmetic type" %
@@ -1884,7 +1940,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
| Econst (_, Ninteger w) =>
(printf `"eval num: " W64 w `": " Pctype t `"\n" %;
ER (w, t))
- | Econst _ => raise Unimplemented
+ | Econst _ => raise Unreachable
| Estrlit _ => P.error pos `"string literal in constant expression" %
| EmemberByV _ | EmemberByP _ =>
P.error pos `"field access in constant expresssion" %
@@ -2477,7 +2533,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
| Tk T.kwDo => loopWrapper parseDoWhile
| Tk T.kwBreak => parseJmp StmtBreak
| Tk T.kwContinue => parseJmp StmtContinue
- | Tk T.kwReturn => parseReturn ctx'
+ | Tk T.kwReturn => parseReturn ctx
| _ => parseStmtExpr ctx
end
@@ -2490,14 +2546,45 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
| _ => P.clerror pos [P.Ctk T.LParen]
end
+ and getReturnExpr ctx =
+ let
+ val (tk, _, ctx') = getTokenCtx ctx
+ in
+ case tk of
+ Tk T.Semicolon => (NONE, ctx')
+ | _ =>
+ let
+ val ((status, ea), ctx) = parseExpr [T.Semicolon] ctx
+ in
+ if status = 0 then
+ P.clerror (#2 $ getTokenCtx ctx) [P.Ctk T.Semicolon]
+ else
+ (SOME ea, ctx)
+ end
+ end
+
and parseReturn ctx =
let
- val ((status, ea), ctx) = parseExpr [T.Semicolon] ctx
+ val (_, pos, ctx) = getTokenCtx ctx
+
+ val (ea, ctx) = getReturnExpr ctx
+
+ val Ctx ctx' = ctx
+ val rt = valOf $ #funcRetType ctx'
+
+ fun ret () = (StmtReturn $ Option.map (convEA rt) ea, ctx)
in
- if status = 0 then
- P.clerror (#2 $ getTokenCtx ctx) [P.Ctk T.Semicolon]
- else
- (StmtReturn ea, ctx)
+ case ea of
+ NONE =>
+ if rt = void_t then
+ ret ()
+ else
+ P.error pos `"empty return in non-void function" %
+ | SOME _ =>
+ if rt = void_t then
+ P.error pos `"attempt to return value in void function" %
+ else
+ ret ()
end
and parseExprFor last ctx =
@@ -2673,7 +2760,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
Printf out `"do " A2 pCompBody (off + 1) body
`" " A1 pea cond `";" %
| pstmt' _ (StmtReturn ea) out =
- Printf out `"return " A1 pea ea `";" %
+ Printf out `"return " Popt pea ea `";" %
| pstmt' _ StmtBreak out = Printf out `"break;" %
| pstmt' _ StmtContinue out = Printf out `"continue;" %
@@ -2697,14 +2784,29 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
case id of
NONE => P.error pos `"expected parameter name\n" %
| SOME _ => checkParams tail
+
+ fun checkParamTypes (arg :: args) =
+ if not $ isScalar arg then
+ P.error pos `"function has parameter with non-scalar type" %
+ else
+ checkParamTypes args
+ | checkParamTypes [] = ()
+
+ val (rt, args) = funcParts t
+
+ val () =
+ if isScalar rt orelse rt = void_t then
+ ()
+ else
+ P.error pos `"function return type is not scalar or void" %
in
- checkParams $ valOf params
+ checkParams $ valOf params;
+ checkParamTypes args
end
fun ctxPrepareForFunc ctx t params =
let
- val paramTypes =
- case t of function_t (_, ts) => ts | _ => raise Unreachable
+ val (rt, paramTypes) = funcParts t
fun createLocalVars (acc, scope) [] [] = (acc, scope)
| createLocalVars (acc, scope) (t :: ts) ((SOME id, pos) :: params) =
@@ -2718,8 +2820,10 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
val (localVars, scope) =
createLocalVars ([], Tree.empty) paramTypes params
+
in
- updateCtx ctx s#localVars localVars s#localScopes [scope] %
+ updateCtx ctx s#localVars localVars s#localScopes [scope]
+ s#funcRetType (SOME rt) %
end
fun finishLocalVars (Ctx ctx) = Vector.fromList o rev o #localVars $ ctx