M2.atg 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. COMPILER M2
  2. (* Step 1 — minimal integer pipeline (m2compiler-V3).
  3. Subset: program MODULE + CONST (literal) + VAR INTEGER +
  4. assignment + integer expressions (+ - * DIV MOD, leading sign,
  5. parens). Fresh QBE backend (QbeGen) to gen_ssa/<Module>.ssa;
  6. assemble with qbe, link with cc.
  7. Test convention: a global VAR ExitCode : INTEGER makes generated
  8. $main return its value as the process exit code, else return 0.
  9. Semantic errors reuse the V1/V2/Test2 family: 200 duplicate,
  10. 201 undeclared, 202 module name mismatch, 210 bad assignment,
  11. 211 bad arithmetic, 221 not a type, 230 construct not supported
  12. in step 1 (REAL/STRING literals, non-INTEGER VAR types,
  13. non-literal CONST expressions, imported names as values).
  14. Full language arrives in later steps; the 230s mark its edge. *)
  15. IMPORT SymTab, QbeGen;
  16. CHARACTERS
  17. eol = CHR(13) .
  18. lf = CHR(10) .
  19. letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
  20. digit = "0123456789" .
  21. hexDigit = digit + "ABCDEFabcdef" .
  22. noQuote1 = ANY - "'" - eol .
  23. noQuote2 = ANY - '"' - eol .
  24. IGNORE CHR(9) .. CHR(13)
  25. COMMENTS FROM "(*" TO "*)" NESTED
  26. COMMENTS FROM "//" TO lf
  27. TOKENS
  28. ident = letter { letter | digit } .
  29. integer = digit { digit }
  30. | "0x" hexDigit { hexDigit }
  31. | "0X" hexDigit { hexDigit } .
  32. real = digit { digit } "." { digit }
  33. [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
  34. string = "'" { noQuote1 } "'"
  35. | '"' { noQuote2 } '"' .
  36. PRODUCTIONS
  37. M2
  38. = Unit "." .
  39. (* Units: program modules compile fully; DEFINITION and
  40. IMPLEMENTATION modules parse + check now but lower in step 4
  41. (each ends with one 230); same for nested local modules. *)
  42. Unit
  43. = DefUnit
  44. | ImplUnit
  45. | ProgModule .
  46. DefUnit (. VAR m1, m2: SymTab.Name; .)
  47. = "DEFINITION" "MODULE"
  48. GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
  49. IF ~SymTab.Enter(m1,
  50. SymTab.KindModule) THEN
  51. SemError(200) END; .)
  52. ";"
  53. { Import }
  54. { ConstBlock | OpaqueBlock | VarBlock }
  55. "END"
  56. GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
  57. SemError(202) END; .)
  58. (. QbeGen.CloseModule;
  59. SemError(230);
  60. SymTab.PrintTable; .) .
  61. ImplUnit (. VAR m1, m2: SymTab.Name; .)
  62. = "IMPLEMENTATION" "MODULE"
  63. GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
  64. IF ~SymTab.Enter(m1,
  65. SymTab.KindModule) THEN
  66. SemError(200) END; .)
  67. ";"
  68. { Import }
  69. DeclSeq
  70. [ "BEGIN" (. QbeGen.BeginBody; .)
  71. [ StatSeq ] ]
  72. "END"
  73. GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
  74. SemError(202) END; .)
  75. (. QbeGen.CloseModule;
  76. SemError(230);
  77. SymTab.PrintTable; .) .
  78. ProgModule (. VAR m1, m2: SymTab.Name; .)
  79. = "MODULE"
  80. GetIdent<m1> (. SymTab.Init; QbeGen.OpenModule(m1);
  81. IF ~SymTab.Enter(m1,
  82. SymTab.KindModule) THEN
  83. SemError(200) END; .)
  84. [ Priority ]
  85. ";"
  86. { Import }
  87. DeclSeq
  88. [ "BEGIN" (. QbeGen.BeginBody; .)
  89. [ StatSeq ] ]
  90. "END"
  91. GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
  92. SemError(202) END; .)
  93. (. QbeGen.EndModule;
  94. SymTab.PrintTable; .) .
  95. DeclSeq
  96. = { ConstBlock | VarBlock | NestedModule ";" } .
  97. (* Local module, Wirth form. Parses + checks fully (own scope);
  98. lowering waits for step 4, marked by one 230 at END. *)
  99. NestedModule (. VAR m1, m2: SymTab.Name; .)
  100. = "MODULE"
  101. GetIdent<m1> (. IF ~SymTab.Enter(m1,
  102. SymTab.KindModule) THEN
  103. SemError(200) END;
  104. SymTab.PushScope; .)
  105. [ Priority ]
  106. ";"
  107. { Import }
  108. [ Export ]
  109. DeclSeq
  110. [ "BEGIN"
  111. [ StatSeq ] ]
  112. "END"
  113. GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
  114. SemError(202) END;
  115. SymTab.PopScope;
  116. SemError(230); .) .
  117. Priority
  118. = "[" integer "]" (. SemError(230); .) .
  119. Export (. VAR nm: SymTab.Name; .)
  120. = "EXPORT" (* names wire up in step 4 *)
  121. [ "QUALIFIED" ]
  122. GetIdent<nm>
  123. { "," GetIdent<nm> }
  124. ";" .
  125. Import (. VAR n: SymTab.Name; .)
  126. = "FROM"
  127. GetIdent<n> (. IF ~SymTab.Enter(n,
  128. SymTab.KindImport) THEN
  129. SemError(200) END; .)
  130. "IMPORT"
  131. ImpList ";"
  132. | "IMPORT"
  133. ImpList ";" .
  134. ImpList (. VAR n: SymTab.Name; .)
  135. = GetIdent<n> (. IF ~SymTab.Enter(n,
  136. SymTab.KindImport) THEN
  137. SemError(200) END; .)
  138. { ","
  139. GetIdent<n> (. IF ~SymTab.Enter(n,
  140. SymTab.KindImport) THEN
  141. SemError(200) END; .) } .
  142. (* Opaque TYPE declarations (definition modules). The targetless
  143. alias resolves to InvalidType until step 4 completes it. *)
  144. OpaqueBlock
  145. = "TYPE" { OpaqueDecl ";" } .
  146. OpaqueDecl (. VAR n: SymTab.Name; .)
  147. = GetIdent<n> (. IF ~SymTab.Enter(n,
  148. SymTab.KindType) THEN
  149. SemError(200) END;
  150. SymTab.SetSymType(n,
  151. SymTab.NewAlias()); .) .
  152. ConstBlock
  153. = "CONST" { ConstDecl ";" } .
  154. ConstDecl (. VAR n: SymTab.Name;
  155. t: SymTab.TypeIndex;
  156. qv: QbeGen.QVal;
  157. cls: INTEGER; .)
  158. = GetIdent<n> (. IF ~SymTab.Enter(n,
  159. SymTab.KindConst) THEN
  160. SemError(200) END; .)
  161. "="
  162. Expr<t, qv> (. SymTab.SetSymType(n, t);
  163. cls := SymTab.ClassOf(t);
  164. IF cls = SymTab.ClStr THEN
  165. SemError(230)
  166. ELSIF ~QbeGen.IsImm(qv) THEN
  167. SemError(230) END;
  168. QbeGen.DeclConst(n, qv, t); .) .
  169. VarBlock
  170. = "VAR" { VarDecl ";" } .
  171. VarDecl (. VAR n, nm: SymTab.Name;
  172. t: SymTab.TypeIndex;
  173. i: CARDINAL;
  174. cls: INTEGER; .)
  175. = VarIdents ":"
  176. GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
  177. SemError(201);
  178. t := SymTab.InvalidType
  179. ELSIF (SymTab.SymKind(n) #
  180. SymTab.KindType)
  181. & (SymTab.SymKind(n) #
  182. SymTab.KindPredef) THEN
  183. SemError(221);
  184. t := SymTab.InvalidType
  185. ELSE t := SymTab.SymType(n)
  186. END;
  187. cls := SymTab.ClassOf(t);
  188. IF (t # SymTab.InvalidType)
  189. & (cls # SymTab.ClInt) THEN
  190. SemError(230) END;
  191. i := 0;
  192. WHILE i < SymTab.PendCount() DO
  193. SymTab.PendName(i, nm);
  194. QbeGen.DeclVar(nm, t);
  195. INC(i)
  196. END;
  197. SymTab.FixPending(t); .) .
  198. VarIdents (. VAR n: SymTab.Name; .)
  199. = GetIdent<n> (. IF ~SymTab.EnterPending(n,
  200. SymTab.KindVar) THEN
  201. SemError(200) END; .)
  202. { ","
  203. GetIdent<n> (. IF ~SymTab.EnterPending(n,
  204. SymTab.KindVar) THEN
  205. SemError(200) END; .) } .
  206. StatSeq
  207. = Statement { ";" Statement } .
  208. Statement
  209. = Assign .
  210. Assign (. VAR dt, et: SymTab.TypeIndex;
  211. dk: INTEGER;
  212. qd, qe: QbeGen.QVal;
  213. qn: SymTab.Name; .)
  214. = Design<dt, dk, qd, qn> ":="
  215. Expr<et, qe> (. IF (dt # SymTab.InvalidType)
  216. & (dk # SymTab.KindVar) THEN
  217. SemError(210)
  218. ELSIF ~SymTab.Assignable(et,
  219. dt) THEN
  220. SemError(210) END;
  221. IF (dk = SymTab.KindVar)
  222. & (dt # SymTab.InvalidType)
  223. & (et # SymTab.InvalidType) THEN
  224. QbeGen.StoreVar(qn, qe, FALSE)
  225. END; .) .
  226. (* Designator, step-1 form: scalar variables and constants only.
  227. No suffixes (field/index/deref are syntax errors in step 1). *)
  228. Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  229. VAR q: QbeGen.QVal; VAR qn: SymTab.Name>
  230. (. VAR n: SymTab.Name;
  231. cls: INTEGER; .)
  232. = GetIdent<n> (. QbeGen.CopyOp(n, qn);
  233. IF ~SymTab.Lookup(n) THEN
  234. SemError(201);
  235. t := SymTab.InvalidType;
  236. k := -1;
  237. QbeGen.CopyOp("0", q)
  238. ELSE
  239. t := SymTab.SymType(n);
  240. k := SymTab.SymKind(n);
  241. IF k = SymTab.KindConst THEN
  242. IF SymTab.Equal(n,
  243. "TRUE") THEN
  244. t := SymTab.BoolType();
  245. QbeGen.CopyOp("1", q)
  246. ELSIF SymTab.Equal(n,
  247. "FALSE") THEN
  248. t := SymTab.BoolType();
  249. QbeGen.CopyOp("0", q)
  250. ELSE
  251. cls :=
  252. SymTab.ClassOf(t);
  253. IF (t #
  254. SymTab.InvalidType)
  255. & (cls = SymTab.ClInt) THEN
  256. QbeGen.LoadVar(n,
  257. FALSE, q)
  258. ELSE
  259. QbeGen.CopyOp("0", q)
  260. END
  261. END
  262. ELSIF k = SymTab.KindVar THEN
  263. cls :=
  264. SymTab.ClassOf(t);
  265. IF cls = SymTab.ClInt THEN
  266. QbeGen.LoadVar(n,
  267. FALSE, q)
  268. ELSE SemError(230);
  269. QbeGen.CopyOp("0", q)
  270. END
  271. ELSE QbeGen.CopyOp("0", q);
  272. IF k = SymTab.KindImport THEN
  273. SemError(230)
  274. END
  275. END
  276. END; .) .
  277. Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  278. = SimExpr<t, q> .
  279. SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  280. (. VAR t2, res2: SymTab.TypeIndex;
  281. op: INTEGER;
  282. q2, qt: QbeGen.QVal;
  283. neg: BOOLEAN; .)
  284. = (. neg := FALSE; .)
  285. [ "+" | "-" (. neg := TRUE; .) ]
  286. Term<t, q> (. IF neg THEN
  287. IF QbeGen.IsImm(q) THEN
  288. QbeGen.NegFold(q, q)
  289. ELSE QbeGen.NewTemp(qt);
  290. QbeGen.NegQ(q, qt, FALSE);
  291. QbeGen.CopyOp(qt, q)
  292. END
  293. END; .)
  294. { AddOp<op> Term<t2, q2>
  295. (. IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
  296. t := res2
  297. ELSE SemError(211); t := SymTab.InvalidType END;
  298. IF t # SymTab.InvalidType THEN
  299. QbeGen.NewTemp(qt);
  300. IF op = SymTab.OpAdd THEN
  301. QbeGen.Op3("add", qt, q, q2, FALSE)
  302. ELSE
  303. QbeGen.Op3("sub", qt, q, q2, FALSE)
  304. END;
  305. QbeGen.CopyOp(qt, q)
  306. ELSE QbeGen.CopyOp("0", q)
  307. END; .) } .
  308. AddOp<VAR op: INTEGER>
  309. = "+" (. op := SymTab.OpAdd; .)
  310. | "-" (. op := SymTab.OpSub; .) .
  311. Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  312. (. VAR t2, res2: SymTab.TypeIndex;
  313. op: INTEGER;
  314. q2, qt: QbeGen.QVal; .)
  315. = Fact<t, q> { MulOp<op> Fact<t2, q2>
  316. (. IF SymTab.ArithCheck(t, t2,
  317. (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
  318. res2) THEN t := res2
  319. ELSE SemError(211); t := SymTab.InvalidType END;
  320. IF t # SymTab.InvalidType THEN
  321. QbeGen.NewTemp(qt);
  322. IF op = SymTab.OpTimes THEN
  323. QbeGen.Op3("mul", qt, q, q2, FALSE)
  324. ELSIF op = SymTab.OpDiv THEN
  325. QbeGen.Op3("div", qt, q, q2, FALSE)
  326. ELSE
  327. QbeGen.Op3("rem", qt, q, q2, FALSE)
  328. END;
  329. QbeGen.CopyOp(qt, q)
  330. ELSE QbeGen.CopyOp("0", q)
  331. END; .) } .
  332. MulOp<VAR op: INTEGER>
  333. = "*" (. op := SymTab.OpTimes; .)
  334. | "DIV" (. op := SymTab.OpDiv; .)
  335. | "MOD" (. op := SymTab.OpMod; .) .
  336. Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
  337. (. VAR s: ARRAY [0 .. 255] OF CHAR;
  338. et, dt: SymTab.TypeIndex;
  339. dk: INTEGER;
  340. qd: QbeGen.QVal;
  341. qn: SymTab.Name; .)
  342. = integer (. LexString(s);
  343. QbeGen.NormInt(s, q);
  344. t := SymTab.IntType(); .)
  345. | real (. LexString(s);
  346. t := SymTab.RealType();
  347. SemError(230);
  348. QbeGen.CopyOp("0", q); .)
  349. | string (. LexString(s);
  350. IF SymTab.StrLen(s) <= 3 THEN
  351. t := SymTab.CharType();
  352. QbeGen.IntStr(
  353. QbeGen.CharVal(s), q)
  354. ELSE t := SymTab.NewStr();
  355. SemError(230);
  356. QbeGen.CopyOp("0", q)
  357. END; .)
  358. | Design<dt, dk, qd, qn> (. t := dt;
  359. QbeGen.CopyOp(qd, q); .)
  360. | "(" Expr<et, q> ")" (. t := et; .) .
  361. GetIdent<VAR n: SymTab.Name>
  362. = ident (. LexName(n); .) .
  363. END M2.