compvar.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. /*++
  2. Copyright (c) 2016 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. compvar.c
  9. Abstract:
  10. This module implements variable related support for compiling Chalk
  11. source into bytecode.
  12. Author:
  13. Evan Green 9-Jun-2016
  14. Environment:
  15. C
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <stdio.h>
  21. #include "chalkp.h"
  22. #include <minoca/lib/status.h>
  23. #include <minoca/lib/yy.h>
  24. #include "compiler.h"
  25. #include "lang.h"
  26. #include "compsup.h"
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. //
  31. // ------------------------------------------------------ Data Type Definitions
  32. //
  33. //
  34. // ----------------------------------------------- Internal Function Prototypes
  35. //
  36. CK_SYMBOL_INDEX
  37. CkpFindUpvalue (
  38. PCK_COMPILER Compiler,
  39. PCSTR Name,
  40. UINTN Length
  41. );
  42. CK_SYMBOL_INDEX
  43. CkpAddUpvalue (
  44. PCK_COMPILER Compiler,
  45. BOOL IsLocal,
  46. CK_SYMBOL_INDEX Symbol
  47. );
  48. CK_SYMBOL_INDEX
  49. CkpResolveLocal (
  50. PCK_COMPILER Compiler,
  51. PCSTR Name,
  52. UINTN Length
  53. );
  54. CK_SYMBOL_INDEX
  55. CkpFindFunctionDeclaration (
  56. PCK_COMPILER Compiler,
  57. PCK_FUNCTION_SIGNATURE Signature,
  58. BOOL Remove
  59. );
  60. //
  61. // -------------------------------------------------------------------- Globals
  62. //
  63. //
  64. // ------------------------------------------------------------------ Functions
  65. //
  66. CK_SYMBOL_INDEX
  67. CkpDeclareMethod (
  68. PCK_COMPILER Compiler,
  69. PCK_FUNCTION_SIGNATURE Signature,
  70. BOOL IsStatic,
  71. PLEXER_TOKEN NameToken,
  72. PSTR Name,
  73. UINTN Length
  74. )
  75. /*++
  76. Routine Description:
  77. This routine declares a method with the given signature, giving it a slot
  78. in the giant global method table, and giving it a slot in the class methods.
  79. Arguments:
  80. Compiler - Supplies a pointer to the compiler.
  81. Signature - Supplies a pointer to the function signature information.
  82. IsStatic - Supplies a boolean indicating if this is a static method or not.
  83. NameToken - Supplies a pointer to the function name token, for non-method
  84. functions.
  85. Name - Supplies a pointer to the signature string.
  86. Length - Supplies the length of the signature string, not including the
  87. null terminator.
  88. Return Value:
  89. Returns the index into the table of methods for this function's signature.
  90. --*/
  91. {
  92. PCK_CLASS_COMPILER EnclosingClass;
  93. CK_SYMBOL_INDEX Index;
  94. PCK_INT_ARRAY MethodArray;
  95. PSTR StaticString;
  96. CK_SYMBOL_INDEX Symbol;
  97. //
  98. // If there's no enclosing class, then this is a local or global function
  99. // being declared. Create a variable with its name.
  100. //
  101. EnclosingClass = Compiler->EnclosingClass;
  102. if (EnclosingClass == NULL) {
  103. CK_ASSERT(IsStatic == FALSE);
  104. //
  105. // First try to find an existing declaration.
  106. //
  107. Symbol = CkpFindFunctionDeclaration(Compiler, Signature, TRUE);
  108. if (Symbol != -1) {
  109. return Symbol;
  110. }
  111. return CkpDeclareVariable(Compiler, NameToken);
  112. }
  113. Symbol = CkpGetSignatureSymbol(Compiler, Signature);
  114. //
  115. // Make sure this class doesn't already have this method.
  116. //
  117. if (IsStatic != FALSE) {
  118. StaticString = "static ";
  119. MethodArray = &(EnclosingClass->StaticMethods);
  120. } else {
  121. StaticString = "";
  122. MethodArray = &(EnclosingClass->Methods);
  123. }
  124. for (Index = 0; Index < MethodArray->Count; Index += 1) {
  125. if (MethodArray->Data[Index] == Symbol) {
  126. CkpCompileError(Compiler,
  127. NULL,
  128. "Class %s already defines %smethod '%s'",
  129. EnclosingClass->Name->Value,
  130. StaticString,
  131. Name);
  132. break;
  133. }
  134. }
  135. CkpArrayAppend(Compiler->Parser->Vm, MethodArray, Symbol);
  136. return Symbol;
  137. }
  138. CK_SYMBOL_INDEX
  139. CkpGetSignatureSymbol (
  140. PCK_COMPILER Compiler,
  141. PCK_FUNCTION_SIGNATURE Signature
  142. )
  143. /*++
  144. Routine Description:
  145. This routine finds or creates a symbol index in the giant array of all
  146. method signatures.
  147. Arguments:
  148. Compiler - Supplies a pointer to the compiler.
  149. Signature - Supplies a pointer to the function signature information.
  150. Return Value:
  151. Returns the index into the table of methods for this function's signature.
  152. --*/
  153. {
  154. UINTN Length;
  155. CHAR Name[CK_MAX_METHOD_SIGNATURE];
  156. Length = sizeof(Name);
  157. CkpPrintSignature(Signature, Name, &Length);
  158. return CkpGetMethodSymbol(Compiler, Name, Length);
  159. }
  160. CK_SYMBOL_INDEX
  161. CkpGetMethodSymbol (
  162. PCK_COMPILER Compiler,
  163. PSTR Name,
  164. UINTN Length
  165. )
  166. /*++
  167. Routine Description:
  168. This routine returns the symbol for the given signature. If it did not
  169. previously exist, it is created.
  170. Arguments:
  171. Compiler - Supplies a pointer to the compiler.
  172. Name - Supplies a pointer to the method signature string.
  173. Length - Supplies the length of the method name, not including the null
  174. terminator.
  175. Return Value:
  176. Returns the index in the symbol table of method names.
  177. --*/
  178. {
  179. CK_SYMBOL_INDEX Symbol;
  180. Symbol = CkpStringTableEnsure(Compiler->Parser->Vm,
  181. &(Compiler->Function->Module->Strings),
  182. Name,
  183. Length);
  184. return Symbol;
  185. }
  186. PCK_CLASS_COMPILER
  187. CkpGetClassCompiler (
  188. PCK_COMPILER Compiler
  189. )
  190. /*++
  191. Routine Description:
  192. This routine walks up the compiler chain looking for the most recent class
  193. being defined.
  194. Arguments:
  195. Compiler - Supplies a pointer to the compiler.
  196. Return Value:
  197. Returns the innermost class being defined.
  198. NULL if a class is not currently being defined.
  199. --*/
  200. {
  201. while (Compiler != NULL) {
  202. if (Compiler->EnclosingClass != NULL) {
  203. return Compiler->EnclosingClass;
  204. }
  205. Compiler = Compiler->Parent;
  206. }
  207. return NULL;
  208. }
  209. VOID
  210. CkpLoadCoreVariable (
  211. PCK_COMPILER Compiler,
  212. PSTR Name
  213. )
  214. /*++
  215. Routine Description:
  216. This routine pushes one of the module-level variables from the core onto
  217. the stack.
  218. Arguments:
  219. Compiler - Supplies a pointer to the compiler.
  220. Name - Supplies a pointer to the core name to load.
  221. Return Value:
  222. None. The core variable is pushed onto the stack.
  223. --*/
  224. {
  225. CK_SYMBOL_INDEX Symbol;
  226. Symbol = CkpStringTableFind(&(Compiler->Parser->Module->VariableNames),
  227. Name,
  228. strlen(Name));
  229. CK_ASSERT(Symbol >= 0);
  230. CkpEmitShortOp(Compiler, CkOpLoadModuleVariable, Symbol);
  231. return;
  232. }
  233. VOID
  234. CkpLoadThis (
  235. PCK_COMPILER Compiler,
  236. PLEXER_TOKEN Token
  237. )
  238. /*++
  239. Routine Description:
  240. This routine loads the "this" local variable.
  241. Arguments:
  242. Compiler - Supplies a pointer to the compiler.
  243. Token - Supplies a pointer to the token, to point to in case it was an
  244. inappropriate scope for this.
  245. Return Value:
  246. None.
  247. --*/
  248. {
  249. CK_VARIABLE This;
  250. This = CkpResolveNonGlobal(Compiler, "this", 4);
  251. if (This.Index == -1) {
  252. CkpCompileError(Compiler, Token, "\"this\" used outside class method");
  253. return;
  254. }
  255. CkpLoadVariable(Compiler, This);
  256. return;
  257. }
  258. CK_VARIABLE
  259. CkpResolveNonGlobal (
  260. PCK_COMPILER Compiler,
  261. PCSTR Name,
  262. UINTN Length
  263. )
  264. /*++
  265. Routine Description:
  266. This routine finds the local variable or upvalue with the given name. It
  267. will not find module level variables.
  268. Arguments:
  269. Compiler - Supplies a pointer to the compiler.
  270. Name - Supplies the name of the variable to find.
  271. Length - Supplies the length of the name, not including the null terminator.
  272. Return Value:
  273. Returns the variable information on success.
  274. --*/
  275. {
  276. CK_VARIABLE Variable;
  277. Variable.Scope = CkScopeLocal;
  278. Variable.Index = CkpResolveLocal(Compiler, Name, Length);
  279. if (Variable.Index == -1) {
  280. Variable.Scope = CkScopeUpvalue;
  281. Variable.Index = CkpFindUpvalue(Compiler, Name, Length);
  282. if (Variable.Index == -1) {
  283. Variable.Scope = CkScopeInvalid;
  284. }
  285. }
  286. return Variable;
  287. }
  288. VOID
  289. CkpLoadVariable (
  290. PCK_COMPILER Compiler,
  291. CK_VARIABLE Variable
  292. )
  293. /*++
  294. Routine Description:
  295. This routine stores a variable with a previously defined symbol index in
  296. the current scope from the value at the top of the stack.
  297. Arguments:
  298. Compiler - Supplies a pointer to the compiler.
  299. Variable - Supplies the variable to load.
  300. Return Value:
  301. None.
  302. --*/
  303. {
  304. switch (Variable.Scope) {
  305. case CkScopeLocal:
  306. CkpLoadLocal(Compiler, Variable.Index);
  307. break;
  308. case CkScopeUpvalue:
  309. CkpEmitByteOp(Compiler, CkOpLoadUpvalue, Variable.Index);
  310. break;
  311. case CkScopeModule:
  312. CkpEmitShortOp(Compiler, CkOpLoadModuleVariable, Variable.Index);
  313. break;
  314. default:
  315. CK_ASSERT(FALSE);
  316. break;
  317. }
  318. return;
  319. }
  320. VOID
  321. CkpDefineVariable (
  322. PCK_COMPILER Compiler,
  323. CK_SYMBOL_INDEX Symbol
  324. )
  325. /*++
  326. Routine Description:
  327. This routine stores a variable with a previously defined symbol index in
  328. the current scope from the value at the top of the stack.
  329. Arguments:
  330. Compiler - Supplies a pointer to the compiler.
  331. Symbol - Supplies the symbol being defined.
  332. Return Value:
  333. None.
  334. --*/
  335. {
  336. //
  337. // If this is a local, the result of the initializer now on the stack is in
  338. // just the right place. Do nothing.
  339. //
  340. if (Compiler->ScopeDepth >= 0) {
  341. return;
  342. }
  343. //
  344. // Store the value into the module level variable.
  345. //
  346. CkpEmitShortOp(Compiler, CkOpStoreModuleVariable, Symbol);
  347. CkpEmitOp(Compiler, CkOpPop);
  348. return;
  349. }
  350. CK_SYMBOL_INDEX
  351. CkpDeclareVariable (
  352. PCK_COMPILER Compiler,
  353. PLEXER_TOKEN Token
  354. )
  355. /*++
  356. Routine Description:
  357. This routine creates a new variable slot in the current scope.
  358. Arguments:
  359. Compiler - Supplies a pointer to the compiler.
  360. Token - Supplies the token containing the name of the variable.
  361. Return Value:
  362. Returns the index of the new variable.
  363. --*/
  364. {
  365. CK_SYMBOL_INDEX Index;
  366. PCK_LOCAL Local;
  367. PCSTR Name;
  368. CK_SYMBOL_INDEX Symbol;
  369. if (Token->Size > CK_MAX_NAME) {
  370. CkpCompileError(Compiler, Token, "Name too long");
  371. return -1;
  372. }
  373. Name = Compiler->Parser->Source + Token->Position;
  374. if (Compiler->ScopeDepth == -1) {
  375. Symbol = CkpDefineModuleVariable(Compiler->Parser->Vm,
  376. Compiler->Parser->Module,
  377. Name,
  378. Token->Size,
  379. CK_NULL_VALUE);
  380. if (Symbol == -1) {
  381. CkpCompileError(Compiler,
  382. Token,
  383. "Module variable is already defined");
  384. } else if (Symbol == -2) {
  385. CkpCompileError(Compiler, Token, "Too many module level variables");
  386. }
  387. return Symbol;
  388. }
  389. //
  390. // Search for a local that might already be in this scope.
  391. //
  392. for (Index = Compiler->LocalCount - 1; Index >= 0; Index -= 1) {
  393. Local = &(Compiler->Locals[Index]);
  394. //
  395. // Stop looking if an outer scope is hit.
  396. //
  397. if (Local->Scope < Compiler->ScopeDepth) {
  398. break;
  399. }
  400. if ((Local->Length == Token->Size) &&
  401. (CkCompareMemory(Local->Name, Name, Local->Length) == 0)) {
  402. CkpCompileError(Compiler,
  403. Token,
  404. "Variable already declared in this scope");
  405. return Index;
  406. }
  407. }
  408. if (Compiler->LocalCount >= CK_MAX_LOCALS) {
  409. CkpCompileError(Compiler, Token, "Too many locals");
  410. return -1;
  411. }
  412. return CkpAddLocal(Compiler, Name, Token->Size);
  413. }
  414. VOID
  415. CkpPushScope (
  416. PCK_COMPILER Compiler
  417. )
  418. /*++
  419. Routine Description:
  420. This routine pushes a new local variable scope in the compiler.
  421. Arguments:
  422. Compiler - Supplies a pointer to the compiler.
  423. Return Value:
  424. None.
  425. --*/
  426. {
  427. Compiler->ScopeDepth += 1;
  428. return;
  429. }
  430. VOID
  431. CkpPopScope (
  432. PCK_COMPILER Compiler
  433. )
  434. /*++
  435. Routine Description:
  436. This routine pops the most recent local variable scope, and clears any
  437. knowledge of local variables defined at that scope.
  438. Arguments:
  439. Compiler - Supplies a pointer to the compiler.
  440. Return Value:
  441. None.
  442. --*/
  443. {
  444. CK_SYMBOL_INDEX Index;
  445. CK_SYMBOL_INDEX Popped;
  446. //
  447. // Discard declarations.
  448. //
  449. Index = Compiler->DeclarationCount - 1;
  450. while ((Index >= 0) &&
  451. (Compiler->Declarations[Index].Scope >= Compiler->ScopeDepth)) {
  452. Index -= 1;
  453. }
  454. Popped = CkpDiscardLocals(Compiler, Compiler->ScopeDepth);
  455. Compiler->LocalCount -= Popped;
  456. Compiler->StackSlots -= Popped;
  457. Compiler->ScopeDepth -= 1;
  458. return;
  459. }
  460. CK_SYMBOL_INDEX
  461. CkpDiscardLocals (
  462. PCK_COMPILER Compiler,
  463. LONG Depth
  464. )
  465. /*++
  466. Routine Description:
  467. This routine emits pop instructions to discard local variables up to a
  468. given depth. This doesn't actually undeclare the variables.
  469. Arguments:
  470. Compiler - Supplies a pointer to the compiler.
  471. Depth - Supplies the depth of locals to discard.
  472. Return Value:
  473. Returns the number of symbols popped.
  474. --*/
  475. {
  476. CK_SYMBOL_INDEX Index;
  477. CK_ASSERT(Compiler->ScopeDepth >= 0);
  478. Index = Compiler->LocalCount - 1;
  479. while ((Index >= 0) && (Compiler->Locals[Index].Scope >= Depth)) {
  480. //
  481. // If the local was closed over, make sure the upvalue gets closed as
  482. // this variable goes out of scope. Emit the byte directly as opposed
  483. // to the op because the stack effect shouldn't be tracked.
  484. //
  485. if (Compiler->Locals[Index].IsUpvalue != FALSE) {
  486. CkpEmitByte(Compiler, CkOpCloseUpvalue);
  487. } else {
  488. CkpEmitByte(Compiler, CkOpPop);
  489. }
  490. Index -= 1;
  491. }
  492. return Compiler->LocalCount - Index - 1;
  493. }
  494. VOID
  495. CkpLoadLocal (
  496. PCK_COMPILER Compiler,
  497. CK_SYMBOL_INDEX Symbol
  498. )
  499. /*++
  500. Routine Description:
  501. This routine loads a local variable and pushes it onto the stack.
  502. Arguments:
  503. Compiler - Supplies a pointer to the compiler.
  504. Symbol - Supplies the index of the local variable to load.
  505. Return Value:
  506. None.
  507. --*/
  508. {
  509. if (Symbol <= 8) {
  510. CkpEmitOp(Compiler, CkOpLoadLocal0 + Symbol);
  511. } else {
  512. CkpEmitByteOp(Compiler, CkOpLoadLocal, Symbol);
  513. }
  514. return;
  515. }
  516. CK_SYMBOL_INDEX
  517. CkpAddLocal (
  518. PCK_COMPILER Compiler,
  519. PCSTR Name,
  520. UINTN Length
  521. )
  522. /*++
  523. Routine Description:
  524. This routine unconditionally creates a new local variable with the given
  525. name.
  526. Arguments:
  527. Compiler - Supplies a pointer to the compiler.
  528. Name - Supplies a pointer to the name of the variable. This pointer will be
  529. used directly.
  530. Length - Supplies the length of the local in bytes, not including the
  531. null terminator.
  532. Return Value:
  533. Returns the index of the symbol.
  534. -1 on error.
  535. --*/
  536. {
  537. PCK_LOCAL Local;
  538. PVOID NewBuffer;
  539. UINTN NewCapacity;
  540. if (Compiler->LocalCount >= Compiler->LocalCapacity) {
  541. NewCapacity = Compiler->LocalCapacity * 2;
  542. NewBuffer = CkpReallocate(Compiler->Parser->Vm,
  543. Compiler->Locals,
  544. Compiler->LocalCapacity * sizeof(CK_LOCAL),
  545. NewCapacity * sizeof(CK_LOCAL));
  546. if (NewBuffer == NULL) {
  547. return -1;
  548. }
  549. Compiler->Locals = NewBuffer;
  550. Compiler->LocalCapacity = NewCapacity;
  551. }
  552. Local = &(Compiler->Locals[Compiler->LocalCount]);
  553. Local->Name = Name;
  554. Local->Length = Length;
  555. Local->Scope = Compiler->ScopeDepth;
  556. Local->IsUpvalue = FALSE;
  557. Compiler->LocalCount += 1;
  558. return Compiler->LocalCount - 1;
  559. }
  560. CK_SYMBOL_INDEX
  561. CkpAddConstant (
  562. PCK_COMPILER Compiler,
  563. CK_VALUE Constant
  564. )
  565. /*++
  566. Routine Description:
  567. This routine adds a new constant value to the current function.
  568. Arguments:
  569. Compiler - Supplies a pointer to the compiler.
  570. Constant - Supplies the constant to add.
  571. Return Value:
  572. Returns the index of the constant.
  573. -1 if the compiler already has an error.
  574. --*/
  575. {
  576. PCK_OBJECT Object;
  577. if (Compiler->Parser->Errors != 0) {
  578. return -1;
  579. }
  580. if (Compiler->Function->Constants.Count < CK_MAX_CONSTANTS) {
  581. if (CK_IS_OBJECT(Constant)) {
  582. Object = CK_AS_OBJECT(Constant);
  583. //
  584. // Strings belong in their own constant table.
  585. //
  586. CK_ASSERT(Object->Type != CkObjectString);
  587. CkpPushRoot(Compiler->Parser->Vm, Object);
  588. }
  589. CkpArrayAppend(Compiler->Parser->Vm,
  590. &(Compiler->Function->Constants),
  591. Constant);
  592. if (CK_IS_OBJECT(Constant)) {
  593. CkpPopRoot(Compiler->Parser->Vm);
  594. }
  595. } else {
  596. CkpCompileError(Compiler, NULL, "Too many constants");
  597. }
  598. return Compiler->Function->Constants.Count - 1;
  599. }
  600. CK_SYMBOL_INDEX
  601. CkpAddStringConstant (
  602. PCK_COMPILER Compiler,
  603. CK_VALUE Constant
  604. )
  605. /*++
  606. Routine Description:
  607. This routine adds a new string constant value to the current function.
  608. Arguments:
  609. Compiler - Supplies a pointer to the compiler.
  610. Constant - Supplies the string constant to add.
  611. Return Value:
  612. Returns the index of the constant.
  613. -1 if the compiler already has an error.
  614. --*/
  615. {
  616. CK_SYMBOL_INDEX Index;
  617. CK_ASSERT((CK_IS_OBJECT(Constant)) &&
  618. (CK_AS_OBJECT(Constant)->Type == CkObjectString));
  619. if (Compiler->Parser->Errors != 0) {
  620. return -1;
  621. }
  622. Index = CkpStringTableEnsureValue(Compiler->Parser->Vm,
  623. &(Compiler->Function->Module->Strings),
  624. Constant);
  625. if (Index >= CK_MAX_CONSTANTS) {
  626. CkpCompileError(Compiler, NULL, "Too many string constants");
  627. Index = -1;
  628. }
  629. return Index;
  630. }
  631. VOID
  632. CkpComplainIfAssigning (
  633. PCK_COMPILER Compiler,
  634. PLEXER_TOKEN Token,
  635. PSTR ExpressionName
  636. )
  637. /*++
  638. Routine Description:
  639. This routine complains if the compiler is in the middle of trying to get an
  640. lvalue for assignment.
  641. Arguments:
  642. Compiler - Supplies a pointer to the compiler.
  643. Token - Supplies a token that is part of the expression that is not an
  644. lvalue.
  645. ExpressionName - Supplies a pointer to the name of the expression.
  646. Return Value:
  647. None.
  648. --*/
  649. {
  650. if (Compiler->Assign != FALSE) {
  651. CkpCompileError(Compiler, Token, "%s is not an lvalue", ExpressionName);
  652. }
  653. return;
  654. }
  655. VOID
  656. CkpAddFunctionDeclaration (
  657. PCK_COMPILER Compiler,
  658. PCK_FUNCTION_SIGNATURE Signature,
  659. PLEXER_TOKEN NameToken
  660. )
  661. /*++
  662. Routine Description:
  663. This routine adds a function declaration.
  664. Arguments:
  665. Compiler - Supplies a pointer to the compiler.
  666. Signature - Supplies the function signature.
  667. NameToken - Supplies the name token of the variable.
  668. Return Value:
  669. None.
  670. --*/
  671. {
  672. LONG Index;
  673. PVOID NewBuffer;
  674. ULONG NewCapacity;
  675. CK_SYMBOL_INDEX SignatureSymbol;
  676. CK_SYMBOL_INDEX Symbol;
  677. SignatureSymbol = CkpGetSignatureSymbol(Compiler, Signature);
  678. if (SignatureSymbol == -1) {
  679. return;
  680. }
  681. //
  682. // Make sure there's room for one more, even if it's not needed.
  683. //
  684. if (Compiler->DeclarationCount >= Compiler->DeclarationCapacity) {
  685. if (Compiler->DeclarationCount == 0) {
  686. NewCapacity = 8;
  687. } else {
  688. NewCapacity = Compiler->DeclarationCapacity * 2;
  689. }
  690. NewBuffer = CkpReallocate(
  691. Compiler->Parser->Vm,
  692. Compiler->Declarations,
  693. Compiler->DeclarationCapacity * sizeof(CK_FUNCTION_DECLARATION),
  694. NewCapacity * sizeof(CK_FUNCTION_DECLARATION));
  695. if (NewBuffer == NULL) {
  696. return;
  697. }
  698. Compiler->Declarations = NewBuffer;
  699. Compiler->DeclarationCapacity = NewCapacity;
  700. }
  701. for (Index = Compiler->DeclarationCount - 1; Index >= 0; Index -= 1) {
  702. //
  703. // If there's already a declaration, return it.
  704. //
  705. if ((Compiler->Declarations[Index].Signature == SignatureSymbol) &&
  706. (Compiler->Declarations[Index].Scope == Compiler->ScopeDepth)) {
  707. return;
  708. }
  709. //
  710. // Stop looking if a lower scope is hit.
  711. //
  712. if (Compiler->Declarations[Index].Scope < Compiler->ScopeDepth) {
  713. break;
  714. }
  715. }
  716. Index = Compiler->DeclarationCount;
  717. //
  718. // Add the new declaration. Push a null to instantiate the variable.
  719. //
  720. CkpEmitOp(Compiler, CkOpNull);
  721. Symbol = CkpDeclareVariable(Compiler, NameToken);
  722. CkpDefineVariable(Compiler, Symbol);
  723. Compiler->Declarations[Index].Signature = SignatureSymbol;
  724. Compiler->Declarations[Index].Scope = Compiler->ScopeDepth;
  725. Compiler->Declarations[Index].Symbol = Symbol;
  726. Compiler->DeclarationCount += 1;
  727. return;
  728. }
  729. //
  730. // --------------------------------------------------------- Internal Functions
  731. //
  732. CK_SYMBOL_INDEX
  733. CkpFindUpvalue (
  734. PCK_COMPILER Compiler,
  735. PCSTR Name,
  736. UINTN Length
  737. )
  738. /*++
  739. Routine Description:
  740. This routine attempts to find an upvalue, and notes its use in the current
  741. compiler.
  742. Arguments:
  743. Compiler - Supplies a pointer to the compiler.
  744. Name - Supplies a pointer to the name of the variable.
  745. Length - Supplies the length of the upvalue in bytes, not including the
  746. null terminator.
  747. Return Value:
  748. Returns the index of the symbol.
  749. -1 on error.
  750. --*/
  751. {
  752. CK_SYMBOL_INDEX Symbol;
  753. //
  754. // If this is the top level compiler, then it's not there.
  755. //
  756. if (Compiler->Parent == NULL) {
  757. return -1;
  758. }
  759. //
  760. // Try to find it as a local in the parent function.
  761. //
  762. Symbol = CkpResolveLocal(Compiler->Parent, Name, Length);
  763. if (Symbol != -1) {
  764. //
  765. // Note that variable as an upvalue in the parent.
  766. //
  767. Compiler->Parent->Locals[Symbol].IsUpvalue = TRUE;
  768. return CkpAddUpvalue(Compiler, TRUE, Symbol);
  769. }
  770. //
  771. // Recurse to see if it's a variable in the enclosing function. This
  772. // recursion will create upvalues up the function definition stack.
  773. //
  774. Symbol = CkpFindUpvalue(Compiler->Parent, Name, Length);
  775. if (Symbol != -1) {
  776. return CkpAddUpvalue(Compiler, FALSE, Symbol);
  777. }
  778. //
  779. // The recursion went all the way up and didn't find anything.
  780. //
  781. return -1;
  782. }
  783. CK_SYMBOL_INDEX
  784. CkpAddUpvalue (
  785. PCK_COMPILER Compiler,
  786. BOOL IsLocal,
  787. CK_SYMBOL_INDEX Symbol
  788. )
  789. /*++
  790. Routine Description:
  791. This routine adds an upvalue to the compiler's current list of upvalues, or
  792. at least ensures it is already known in the compiler.
  793. Arguments:
  794. Compiler - Supplies a pointer to the compiler.
  795. IsLocal - Supplies a boolean indicating if the new upvalue closes over a
  796. local or another upvalue.
  797. Symbol - Supplies the variable index that is an upvalue.
  798. Return Value:
  799. Returns the index of the upvalue.
  800. -1 on error.
  801. --*/
  802. {
  803. CK_SYMBOL_INDEX Count;
  804. CK_SYMBOL_INDEX Index;
  805. PVOID NewBuffer;
  806. UINTN NewCapacity;
  807. PCK_COMPILER_UPVALUE Upvalue;
  808. Count = Compiler->Function->UpvalueCount;
  809. for (Index = 0; Index < Count; Index += 1) {
  810. Upvalue = &(Compiler->Upvalues[Index]);
  811. if ((Upvalue->Index == Symbol) && (Upvalue->IsLocal == IsLocal)) {
  812. return Index;
  813. }
  814. }
  815. if (Count >= Compiler->UpvalueCapacity) {
  816. NewCapacity = Compiler->UpvalueCapacity * 2;
  817. if (NewCapacity == 0) {
  818. NewCapacity = 32;
  819. }
  820. NewBuffer = CkpReallocate(
  821. Compiler->Parser->Vm,
  822. Compiler->Upvalues,
  823. Compiler->UpvalueCapacity * sizeof(CK_COMPILER_UPVALUE),
  824. NewCapacity * sizeof(CK_COMPILER_UPVALUE));
  825. if (NewBuffer == NULL) {
  826. return -1;
  827. }
  828. Compiler->Upvalues = NewBuffer;
  829. Compiler->UpvalueCapacity = NewCapacity;
  830. }
  831. Compiler->Upvalues[Count].IsLocal = IsLocal;
  832. Compiler->Upvalues[Count].Index = Symbol;
  833. Compiler->Function->UpvalueCount += 1;
  834. return Count;
  835. }
  836. CK_SYMBOL_INDEX
  837. CkpResolveLocal (
  838. PCK_COMPILER Compiler,
  839. PCSTR Name,
  840. UINTN Length
  841. )
  842. /*++
  843. Routine Description:
  844. This routine attempts to find a local variable.
  845. Arguments:
  846. Compiler - Supplies a pointer to the compiler.
  847. Name - Supplies a pointer to the name of the variable.
  848. Length - Supplies the length of the local in bytes, not including the
  849. null terminator.
  850. Return Value:
  851. Returns the index of the symbol.
  852. -1 on error.
  853. --*/
  854. {
  855. CK_SYMBOL_INDEX Index;
  856. //
  857. // Search in reverse order so that the most recently scoped variables are
  858. // found first.
  859. //
  860. for (Index = Compiler->LocalCount - 1;
  861. Index >= 0;
  862. Index -= 1) {
  863. if ((Compiler->Locals[Index].Length == Length) &&
  864. (CkCompareMemory(Compiler->Locals[Index].Name, Name, Length) ==
  865. 0)) {
  866. return Index;
  867. }
  868. }
  869. return -1;
  870. }
  871. CK_SYMBOL_INDEX
  872. CkpFindFunctionDeclaration (
  873. PCK_COMPILER Compiler,
  874. PCK_FUNCTION_SIGNATURE Signature,
  875. BOOL Remove
  876. )
  877. /*++
  878. Routine Description:
  879. This routine finds a function declaration.
  880. Arguments:
  881. Compiler - Supplies a pointer to the compiler.
  882. Signature - Supplies the function signature.
  883. Remove - Supplies a boolean indicating whether to remove the declaration
  884. or not. TRUE is supplied when the function is being defined.
  885. Return Value:
  886. Returns the variable index for the function in the current scope.
  887. --*/
  888. {
  889. ULONG Index;
  890. CK_SYMBOL_INDEX SignatureSymbol;
  891. SignatureSymbol = CkpGetSignatureSymbol(Compiler, Signature);
  892. if (SignatureSymbol == -1) {
  893. return -1;
  894. }
  895. for (Index = 0; Index < Compiler->DeclarationCount; Index += 1) {
  896. if ((Compiler->Declarations[Index].Signature == SignatureSymbol) &&
  897. (Compiler->Declarations[Index].Scope == Compiler->ScopeDepth)) {
  898. if (Remove != FALSE) {
  899. Compiler->Declarations[Index].Signature = -1;
  900. }
  901. return Compiler->Declarations[Index].Symbol;
  902. }
  903. //
  904. // Stop looking if a lower scope is hit.
  905. //
  906. if (Compiler->Declarations[Index].Scope < Compiler->ScopeDepth) {
  907. break;
  908. }
  909. }
  910. return -1;
  911. }