summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--ccross.mlb1
-rw-r--r--ccross.sml3
-rw-r--r--common.sml2
-rw-r--r--dynarray.sig14
-rw-r--r--dynarray.sml55
-rw-r--r--parser.fun435
7 files changed, 457 insertions, 55 deletions
diff --git a/Makefile b/Makefile
index a832a4f..730b8a4 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,6 @@ ffi := -default-ann "allowFFI true" -export-header export.h
caux := caux.c
def:
- mlton $(history) $(ffi) ccross.mlb $(caux)
+ mlton $(history) $(ffi) -default-type word64 ccross.mlb $(caux)
clean:
rm -f ccross export.h
diff --git a/ccross.mlb b/ccross.mlb
index 29f059a..3a4231c 100644
--- a/ccross.mlb
+++ b/ccross.mlb
@@ -12,6 +12,7 @@ in
stream.sig stream.sml
hashtable.sig hashtable.sml
tree.sig tree.sml
+ dynarray.sig dynarray.sml
symtab.sig symtab.fun
tokenizer.sig tokenizer.fun
diff --git a/ccross.sml b/ccross.sml
index 3c8bcf4..d3dcf3c 100644
--- a/ccross.sml
+++ b/ccross.sml
@@ -4,7 +4,8 @@ structure ccross:> CCROSS = struct
Tokenizer(structure ST = ST; structure S = Stream)
structure ppc:> PPC = ppc(structure Tree = Tree; structure T = T)
structure Parser:> PARSER =
- Parser(structure Tree = Tree; structure P = ppc)
+ Parser(structure Tree = Tree; structure P = ppc;
+ structure D = Dynarray)
structure D:> DRIVER = Driver(Parser)
structure ExnHandler:> EXN_HANDLER = ExnHandler
end
diff --git a/common.sml b/common.sml
index 13d9ff8..6b23c4d 100644
--- a/common.sml
+++ b/common.sml
@@ -149,7 +149,7 @@ fun F z = bind A0 (fn (_, mf) => mf ()) z
val I = fn z => bindWith2str Int.toString z
val C = fn z => bindWith2str str z
val B = fn z => bindWith2str Bool.toString z
-val W64 = fn z => bindWith2str Word64.toString z
+val W = fn z => bindWith2str (Word.fmt StringCvt.DEC) z
val R = fn z => bind A1 (fn n => fn (output, _) => app (fn f => f ())
(List.tabulate (n, fn _ => fn () => output " "))) z
diff --git a/dynarray.sig b/dynarray.sig
new file mode 100644
index 0000000..ab3a248
--- /dev/null
+++ b/dynarray.sig
@@ -0,0 +1,14 @@
+signature DYNARRAY = sig
+ type 'a t = (int * 'a option Array.array) ref
+
+ exception OutOfBounds
+
+ val create: int -> 'a t
+ val create0: unit -> 'a t
+
+ val length: 'a t -> int
+
+ val push: 'a t -> 'a -> unit
+ val get: 'a t -> int -> 'a
+ val set: 'a t -> int -> 'a -> unit
+end
diff --git a/dynarray.sml b/dynarray.sml
new file mode 100644
index 0000000..0c1cd7f
--- /dev/null
+++ b/dynarray.sml
@@ -0,0 +1,55 @@
+structure Dynarray: DYNARRAY = struct
+ type 'a t = (int * 'a option Array.array) ref
+
+ exception OutOfBounds
+
+ fun create n =
+ ref (0, Array.array (n, NONE))
+
+ fun create0 () = create 10
+
+ fun length dynarr =
+ let
+ val (len, _) = !dynarr
+ in
+ len
+ end
+
+ fun push dynarr v =
+ let
+ val (len, arr) = !dynarr
+ in
+ if len = Array.length arr then
+ let
+ val arr2 = Array.array (len * 2, NONE)
+ in
+ Array.copy { src = arr, dst = arr2, di = 0 };
+ dynarr := (len, arr2);
+ push dynarr v
+ end
+ else
+ Array.update (arr, len, SOME v);
+ dynarr := (len + 1, arr)
+ end
+
+ fun get dynarr n =
+ let
+ val (len, arr) = !dynarr
+ in
+ if n >= len then
+ raise OutOfBounds
+ else
+ valOf $ Array.sub (arr, n)
+ end
+
+ fun set dynarr n v =
+ let
+ val (len, arr) = !dynarr
+ in
+ if n >= len then
+ raise OutOfBounds
+ else
+ Array.update (arr, n, SOME v)
+ end
+
+end
diff --git a/parser.fun b/parser.fun
index caa755f..f2966b6 100644
--- a/parser.fun
+++ b/parser.fun
@@ -1,8 +1,11 @@
-functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
+functor Parser(structure Tree: TREE; structure P: PPC;
+ structure D: DYNARRAY): PARSER = struct
structure P = P
structure T = P.T
+ type nid = int
+
datatype unop =
UnopPreInc |
UnopPreDec |
@@ -67,8 +70,8 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
Eid of int * id option |
Econst of int * cnum |
Estrlit of int |
- EmemberByV of int * exprAug |
- EmemberByP of int * exprAug |
+ EmemberByV of exprAug * int |
+ EmemberByP of exprAug * int |
EfuncCall of exprAug * exprAug list |
Eternary of exprAug * exprAug * exprAug |
EsizeofType of ctype |
@@ -92,13 +95,19 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
ulong_t |
longlong_t |
ulonglong_t |
+
(*
float_t |
double_t |
*)
pointer_t of int * ctype |
function_t of ctype * ctype list |
- array_t of Word64.word * ctype
+ array_t of Word64.word * ctype |
+ struct_t of
+ { name: nid, size: word, alignment: word,
+ fields: (nid * word * ctype) list } |
+
+ remote_t of int
val typeSizes = [
(char_t, 1), (uchar_t, 1),
@@ -133,6 +142,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
SpecStatic |
SpecRegister
+
type rawDecl = {
id: int option,
pos: P.tkPos,
@@ -186,11 +196,19 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
datatype def = Objects of objDef list | Definition of funcInfo
- type nid = int
-
type scope = (nid, int) Tree.t
+ datatype typeStatus = TsDefined | TsIncomplete | TsNotDefined
+
+ (*
+ * For structures and unions the type name (nid) is duplicated for the
+ * ease of pctype function
+ *)
+ val types: (nid * P.tkPos * ctype) D.t = D.create0 ()
+
datatype ctx = Ctx of {
+ aggrTypeNames: scope,
+
localScopes: scope list,
localVars: (int * P.tkPos * ctype) list,
funcRetType: ctype option,
@@ -208,16 +226,19 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
fun updateCtx (Ctx ctx) = fn z =>
let
- fun from localScopes localVars funcRetType globalDecls
- tokenBuf loopLevel =
- { localScopes, localVars, funcRetType, globalDecls,
- tokenBuf, loopLevel }
+ fun from aggrTypeNames localScopes localVars
+ funcRetType globalDecls tokenBuf loopLevel
+ =
+ { aggrTypeNames, localScopes, localVars,
+ funcRetType, globalDecls, tokenBuf, loopLevel }
- fun to f { localScopes, localVars, funcRetType, globalDecls,
- tokenBuf, loopLevel } =
- f localScopes localVars funcRetType globalDecls tokenBuf loopLevel
+ fun to f { aggrTypeNames, localScopes, localVars,
+ funcRetType, globalDecls, tokenBuf, loopLevel }
+ =
+ f aggrTypeNames localScopes localVars funcRetType
+ globalDecls tokenBuf loopLevel
in
- FRU.makeUpdate6 (from, from, to) ctx (fn (a, f) => z (a, Ctx o f))
+ FRU.makeUpdate7 (from, from, to) ctx (fn (a, f) => z (a, Ctx o f))
end
datatype declParts =
@@ -229,7 +250,8 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
datatype abstructPolicy = APpermitted | APenforced | APprohibited
- datatype specType = StorageSpec of storageSpec | TypeSpec of T.token
+ datatype specType =
+ StorageSpec of storageSpec | TypeSpec of T.token
val binopTable = [
(BrSubscript, T.Invalid, 0, false),
@@ -287,6 +309,12 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
| ulong_t => & ("unsigned long", "L")
| longlong_t => & ("long long", "w")
| ulonglong_t => & ("unsigned long long", "W")
+ | remote_t id =>
+ let
+ val (_, _, t) = D.get types id
+ in
+ pctype short t out
+ end
(*
| float_t => & ("float", "f")
| double_t => & ("double", "d")
@@ -301,6 +329,11 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
`"}" `(if short then "" else " -> ") A2 pctype short ret %
| array_t (n, el) =>
Printf out `"[" `(Word64.toString n) `"]" A2 pctype short el %
+ | struct_t { name, ... } =>
+ if short then
+ Printf out `"r" I name %
+ else
+ Printf out `"struct " P.? name %
end
val Pctype = fn z => bind A1 (pctype false) z
@@ -314,7 +347,9 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
T.kwFloat,
T.kwDouble,
T.kwSigned,
- T.kwUnsigned
+ T.kwUnsigned,
+
+ T.kwStruct
]
fun ts2idx ts =
@@ -329,8 +364,6 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
find 0 typeSpecs
end
- fun idx2ts idx = List.nth (typeSpecs, idx)
-
val tsMaxIdxP1 = length typeSpecs
val prefixes = [
@@ -424,6 +457,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
(repr2id, (id, ctype) :: id2type, trs)
end
+ (*
fun prefixFsmPrint fsm repr2id =
let
fun findRepr id =
@@ -441,6 +475,8 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
Printf out `"[" A1 printRepr' l `"]" %
end
+ fun idx2ts idx = List.nth (typeSpecs, idx)
+
open Array
fun printRow i =
@@ -470,6 +506,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
i := !i + 1
)
end
+ *)
fun buildPrefixFsm () =
let
@@ -529,6 +566,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
fun typeRepr2type typeReprId =
valOf o #1 o Array.sub $ (prefixFsm, typeReprId)
+ (*
fun pTokenL l out =
let
fun pToken (tk, _) out =
@@ -546,6 +584,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
in
Printf out Plist pToken l (",", false) %
end
+ *)
val isIntegral = fn
char_t | uchar_t | short_t | ushort_t | int_t | uint_t
@@ -594,7 +633,13 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
if n < 2 then raise Unreachable else pointer_t (n - 1, t)
| _ => raise Unreachable
+ fun tryGetFields (struct_t { fields, ... }) = SOME fields
+ | tryGetFields (remote_t id) = (tryGetFields o #3 o D.get types) id
+ | tryGetFields _ = NONE
+
fun createCtx fname incDirs = Ctx {
+ aggrTypeNames = Tree.empty,
+
localScopes = [],
localVars = [],
funcRetType = NONE,
@@ -723,7 +768,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
and pexpr e out =
let
- fun mem (id, ea) s = Printf out A1 pea ea `s P.? id %
+ fun mem (ea, id) s = Printf out A1 pea ea `s P.? id %
in
case e of
Eid (nid, id) => Printf out P.? nid `"{" A3 poptN "none" pid id `"}" %
@@ -888,7 +933,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
val (tk, pos2, ctx2) = getTokenCtx ctx1
in
case tk of
- Tk (T.Id id) => (SOME $ makeEA (unop (id, eAug)) pos1, ctx2)
+ Tk (T.Id id) => (SOME $ makeEA (unop (eAug, id)) pos1, ctx2)
| _ => P.clerror pos2 [P.Cid]
end
in
@@ -1220,8 +1265,6 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
and findId (Ctx ctx) pos sizeofOrAddr id =
let
- val () = printf `"findId: " B sizeofOrAddr `"\n" %
-
fun findLocal [] = NONE
| findLocal (scope :: scopes) =
let
@@ -1266,6 +1309,8 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
| pointer_t _ => 13
| array_t _ => 14
| function_t _ => 15
+ | struct_t _ => 16
+ | remote_t id => (typeRank o #3 o D.get types) id
| unknown_t => raise Unreachable
and convEA t (E as EA (_, pos, _, t')) =
@@ -1657,6 +1702,43 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
end
| checkTernary _ _ = raise Unreachable
+ and checkMemberAccess check byP
+ (EA (EmemberByV (ea, field) | EmemberByP (ea, field), pos, _, _))
+ =
+ let
+ val ea = check ea
+
+ val pos' = getPos ea
+ val t = getT ea
+
+ val t =
+ if byP then
+ if isPointer t then
+ pointsTo t
+ else
+ P.error pos' `"expected a pointer to aggregate" %
+ else
+ t
+
+ val fields =
+ case (tryGetFields t, byP) of
+ (NONE, true) =>
+ P.error pos' `"expected a pointer to an aggregate" %
+ | (NONE, false) => P.error pos' `"expected an aggregate" %
+ | (SOME fields, _) => fields
+
+ val e =
+ if byP then
+ EmemberByP (ea, field)
+ else
+ EmemberByV (ea, field)
+ in
+ case List.find (fn (f, _, _) => f = field) fields of
+ NONE => P.error pos `"unknown field" %
+ | SOME (_, _, field_type) => EA (e, pos, true, field_type)
+ end
+ | checkMemberAccess _ _ _ = raise Unreachable
+
and checkExpr ctx sizeofOrAddr (E as EA (e, pos, _, _)) =
let
val check = checkExpr ctx
@@ -1675,7 +1757,9 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
| Ebinop (_, _, _) => checkBinop (check false) E
| Eternary _ => checkTernary (check false) E
| Eunop (_, _) => checkUnop check sizeofOrAddr E
- | _ => E
+ | EmemberByV _ => checkMemberAccess (check false) false E
+ | EmemberByP _ => checkMemberAccess (check false) true E
+ | Econst _ | Estrlit _ => E
end
and tryGetSpec ctx =
@@ -1701,13 +1785,23 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
)
end
- and sizeOfType (pointer_t _) = pointerSize
- | sizeOfType (array_t (n, t)) = Word64.* (n, sizeOfType t)
- | sizeOfType t =
+ and findPrimTypeSize t =
case List.find (fn (t', _) => t' = t) typeSizes of
SOME (_, size) => Word64.fromInt size
| _ => raise Unreachable
+ and alignOfType (pointer_t _) = pointerSize
+ | alignOfType (array_t (_, t)) = alignOfType t
+ | alignOfType (struct_t { alignment, ... }) = alignment
+ | alignOfType (remote_t id) = (alignOfType o #3 o D.get types) id
+ | alignOfType t = findPrimTypeSize t
+
+ and sizeOfType (pointer_t _) = pointerSize
+ | sizeOfType (array_t (n, t)) = Word64.* (n, sizeOfType t)
+ | sizeOfType (struct_t { size, ... }) = size
+ | sizeOfType (remote_t id) = (sizeOfType o #3 o D.get types) id
+ | sizeOfType t = findPrimTypeSize t
+
and sizeofWrapper t = Word64.toInt $ sizeOfType t
and zeroExtend (ER (w, t)) =
@@ -1716,9 +1810,9 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
val minus1 = Word64.notb (Word64.fromInt 0)
val mask = Word64.>> (minus1, 0w64 - size * 0w8)
- val () = printf `"ZH0: " W64 w `"\n" %
+ val () = printf `"ZH0: " W w `"\n" %
val res = Word64.andb (mask, w)
- val () = printf `"ZH1: " W64 res `"\n" %
+ val () = printf `"ZH1: " W res `"\n" %
in
res
end
@@ -1757,7 +1851,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
let
val minus1 = Word64.notb $ Word64.fromInt 0
val res as ER (w, _) = ER (Word64.xorb (minus1, w), t)
- val () = printf `"~ after: " W64 w `"\n" %
+ val () = printf `"~ after: " W w `"\n" %
in
res
end
@@ -1832,7 +1926,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
val left' = conv left
val right' = conv right
- val () = printf `"eval compare: " W64 left' `", " W64 right' `"\n" %
+ val () = printf `"eval compare: " W left' `", " W right' `"\n" %
val res = convResult $ comp (left', right')
in
ER (w64FromBool res, int_t)
@@ -1938,7 +2032,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
case e of
Eid _ => P.error pos `"variable in constant expression" %
| Econst (_, Ninteger w) =>
- (printf `"eval num: " W64 w `": " Pctype t `"\n" %;
+ (printf `"eval num: " W w `": " Pctype t `"\n" %;
ER (w, t))
| Econst _ => raise Unreachable
| Estrlit _ => P.error pos `"string literal in constant expression" %
@@ -1968,42 +2062,274 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
val res = eval' $ EA (e, pos, false, t')
val ER (w, _) = res
- val () = printf `"eval: " W64 w `"\n" %
+ val () = printf `"eval: " W w `"\n" %
in
zeroExtend res
end
and parseDeclPrefix ctx =
let
+ datatype state = TypeId of int | Type of ctype
+
fun collect ctx (storSpec, typeReprId) =
let
val (spec, ctx) = tryGetSpec ctx
in
- case spec of
- NONE =>
- if typeReprId = 0 then
- let
- val (_, pos, _) = getTokenCtx ctx
- val ets = "expected type specifier"
- val etss = "expected type or storage specifier"
- in
- P.error pos `(if isSome storSpec then ets else etss) %
- end
- else
- ((storSpec, typeRepr2type typeReprId), ctx)
- | SOME (StorageSpec spec, pos) => (
+ case (spec, typeReprId) of
+ (NONE, TypeId 0) =>
+ let
+ val (_, pos, _) = getTokenCtx ctx
+ val ets = "expected type specifier"
+ val etss = "expected type or storage specifier"
+ in
+ P.error pos `(if isSome storSpec then ets else etss) %
+ end
+
+ | (NONE, TypeId id) => ((storSpec, typeRepr2type id), ctx)
+ | (NONE, Type t) => ((storSpec, t), ctx)
+
+ | (SOME (StorageSpec spec, pos), _) => (
case storSpec of
NONE => collect ctx (SOME spec, typeReprId)
| SOME _ =>
P.error pos `"storage specifier is already provided" %
)
- | SOME (TypeSpec tk, pos) =>
- collect ctx (storSpec, advanceTypeRepr typeReprId (tk, pos))
+
+ | (SOME (TypeSpec T.kwStruct, _), TypeId 0) =>
+ let
+ val (t, ctx) = processStruct ctx
+ in
+ ((storSpec, t), ctx)
+ end
+ | (SOME (TypeSpec T.kwStruct, pos), _) =>
+ P.error pos `"invalid type specifier" %
+ | (SOME (TypeSpec tk, pos), TypeId id) =>
+ collect ctx (storSpec, TypeId $ advanceTypeRepr id (tk, pos))
+ | (SOME (TypeSpec _, pos), _) =>
+ P.error pos `"invalid type specifier" %
+ end
+ in
+ collect ctx (NONE, TypeId 0)
+ end
+
+ and getStructName ctx =
+ let
+ val (tk, pos, ctx) = getTokenCtx ctx
+ in
+ case tk of
+ Tk (T.Id id) => (id, pos, ctx)
+ | TkBrackets _ =>
+ P.error pos `"anonymous structures are not supported" %
+ | _ => P.error pos `"expected struct name" %
+ end
+
+ and parseStructDeclaration ctx =
+ let
+ val (prefix, ctx) = parseDeclPrefix ctx
+
+ fun convToField ({ pos, spec = SOME _, ... }) =
+ P.error pos `"aggregate field with storage specifier" %
+ | convToField ({ id, pos, spec = NONE, t, ... }) =
+ if isFunc t then
+ P.error pos `"field of function type" %
+ else
+ (valOf id, pos, t)
+
+ fun collect acc ctx =
+ let
+ val (parts, ctx) = parseDeclarator (false, APprohibited) [] ctx
+ val declaredId = assembleDeclarator prefix parts
+
+ val field = convToField declaredId
+ val acc = field :: acc
+
+ val (tk, pos, ctx) = getTokenCtx ctx
+ in
+ case tk of
+ Tk T.Semicolon => (rev acc, ctx)
+ | Tk T.Comma => collect acc ctx
+ | _ => P.clerror pos [P.Ctk T.Semicolon, P.Ctk T.Comma]
end
in
- collect ctx (NONE, 0)
+ collect [] ctx
end
+ and tryGetStructBody pos ctx: (nid * ctype) list option * ctx =
+ let
+ val (tk, _, ctx') = getTokenCtx ctx
+
+ fun checkFieldUniqueness ((id, _, _) :: fs) = (
+ case List.find (fn (id', _, _) => id' = id) fs of
+ SOME (_, pos, _) => P.error pos `"field name is reused" %
+ | NONE => checkFieldUniqueness fs
+ )
+ | checkFieldUniqueness [] = ()
+
+ fun collectFields acc ctx =
+ let
+ val (tk, _, _) = getTokenCtx ctx
+ in
+ case tk of
+ Tk T.EOS =>
+ let
+ val acc = rev acc
+ in
+ if null acc then
+ P.error pos `"empty structures are not supported" %
+ else (
+ checkFieldUniqueness acc;
+ (SOME $ map (fn (id, _, t) => (id, t)) acc, ctx)
+ )
+ end
+ | _ =>
+ let
+ val (fields, ctx) = parseStructDeclaration ctx
+ in
+ collectFields (List.revAppend (fields, acc)) ctx
+ end
+ end
+ in
+ case tk of
+ TkBraces list => ctxWithLayer ctx' list (collectFields [])
+ | _ => (NONE, ctx)
+ end
+
+ and getStructStatus id (Ctx { aggrTypeNames, ... }) =
+ let
+ val bufId = lookup aggrTypeNames id
+
+ (* val () = printf `"Searching for " P.? id `"\n" % *)
+ in
+ case bufId of
+ NONE => TsNotDefined
+ | SOME id =>
+ case #3 $ D.get types id of
+ struct_t { fields = [], ... } => TsIncomplete
+ | _ => TsDefined
+ end
+
+ and getTypeIdFromName id (Ctx { aggrTypeNames, ... }) =
+ valOf $ lookup aggrTypeNames id
+
+ and calcStruct id [] =
+ struct_t { name = id, size = 0w0, alignment = 0w0, fields = [] }
+ | calcStruct id fields =
+ let
+ val alignment: word =
+ List.foldl (fn ((_, t), m) =>
+ let
+ val fa = alignOfType t
+ in
+ if fa > m then fa else m
+ end) 0w0 $ fields
+
+ fun align v align =
+ if v mod align = 0w0 then v else v + align - v mod align
+
+ fun calcSize size [] offsets =
+ if size mod alignment = 0w0 then
+ (size, rev offsets)
+ else
+ (align size alignment, rev offsets)
+ | calcSize size ((_, t) :: fields) offsets =
+ let
+ val fieldOffset = align size (alignOfType t)
+ val size = fieldOffset + sizeOfType t
+
+ val () = printf `"foffset : " W fieldOffset `"\n" %
+ in
+ calcSize size fields (fieldOffset :: offsets)
+ end
+
+ val (size, offsets) =
+ calcSize ((sizeOfType o #2 o hd) fields) (tl fields) [0w0]
+
+ fun zipOffsets (off :: offs) ((id, t) :: fs) =
+ (id, off, t) :: zipOffsets offs fs
+ | zipOffsets [] [] = []
+ | zipOffsets _ _ = raise Unreachable
+ in
+ struct_t { name = id, size, alignment,
+ fields = zipOffsets offsets fields }
+ end
+
+ and Pstruct z =
+ let
+ fun p [] _ = ()
+ | p ((id, offset, t) :: fields) out =
+ Printf out `"\t" W offset `": " P.? id `": "
+ Pctype t `"\n" A1 p fields %
+
+ fun f (struct_t { size, alignment, fields, ... }) out =
+ Printf out `"{ size = " W size `", alignment = " W alignment `"\n"
+ A1 p fields `"}\n" %
+ | f _ _ = raise Unreachable
+ in
+ bind A1 f
+ end z
+
+ (*
+ val Ptk = fn z =>
+ let
+ fun f tk out = Printf out T.Ptk symtab tk %
+ in
+ bind A1 f
+ end z
+ *)
+
+ and registerStruct id _ TsIncomplete NONE ctx =
+ (getTypeIdFromName id ctx, ctx)
+ | registerStruct id _ TsDefined NONE ctx =
+ (getTypeIdFromName id ctx, ctx)
+
+ | registerStruct id pos TsNotDefined body
+ (C as Ctx { aggrTypeNames, ... })
+ =
+ let
+ val newBufId = D.length types
+ val (_, aggrTypeNames) = Tree.insert intCompare aggrTypeNames id newBufId
+
+ val (body', status) =
+ case body of
+ NONE => ([], "incomplete")
+ | SOME body => (body, "complete")
+
+ val newInfo = (id, pos, calcStruct id body')
+ in
+ D.push types newInfo;
+ printf `"new " `status `" struct: " P.? id `":" I id `"\n" %;
+ printf Pstruct (#3 newInfo) %;
+ (newBufId, updateCtx C s#aggrTypeNames aggrTypeNames %)
+ end
+
+ | registerStruct id pos TsIncomplete (SOME body)
+ (C as Ctx { aggrTypeNames, ... })
+ =
+ let
+ val bufId = valOf $ lookup aggrTypeNames id
+ val newInfo = (id, pos, calcStruct id body)
+ in
+ D.set types bufId newInfo;
+ printf `"completing struct: " P.? id `":" I id `"\n" %;
+ printf Pstruct (#3 newInfo) %;
+ (bufId, C)
+ end
+ | registerStruct _ pos TsDefined (SOME _) _ =
+ P.error pos `"struct redefinition" %
+
+ and processStruct ctx =
+ let
+ val (id, pos, ctx) = getStructName ctx
+
+ val status = getStructStatus id ctx
+ val (body, ctx) = tryGetStructBody pos ctx
+
+ val (bufTypeId, ctx) = registerStruct id pos status body ctx
+ in
+ (remote_t bufTypeId, ctx)
+ end
+
+ (*
and Ppart part out =
case part of
Pointer plevel => Printf out `"[" I plevel `"] " %
@@ -2011,6 +2337,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
| AbstructRoot _ => Printf out `":root" %
| FuncApp _ => Printf out `"()" %
| ArrayApplication _ => Printf out `"[]" %
+ *)
and isTypeNameStart tk =
isSome $ List.find
@@ -2197,8 +2524,8 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
| _ => NONE
in
- { id, pos, spec = storSpec, t = complete $ tl parts,
- ini = NONE, params }
+ ({ id, pos, spec = storSpec, t = complete $ tl parts,
+ ini = NONE, params }: rawDecl)
end
fun printIni (IniExpr ea) out = Printf out A1 pea ea %
@@ -2489,8 +2816,12 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
else
(finishNormal $ add toplevMaybe, ctx)
end
+
+ val (tk, _, ctx') = getTokenCtx ctx
in
- collectDeclarators [] ctx
+ case tk of
+ Tk T.Semicolon => (finishNormal [], ctx')
+ | _ => collectDeclarators [] ctx
end
fun skipExpected expectedTk ctx =
@@ -2690,7 +3021,7 @@ functor Parser(structure Tree: TREE; structure P: PPC): PARSER = struct
in
if isTypeNameStart tk then
let
- val (res , ctx) = parseDeclaration ctx
+ val (res, ctx) = parseDeclaration ctx
val inits =
case res of
LocalVarInits l => l