PageRenderTime 222ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/VM/ori_vmVariables.pas

http://orionphp.googlecode.com/
Pascal | 407 lines | 319 code | 57 blank | 31 comment | 31 complexity | 22089ea487094cfc9799c45290516dc7 MD5 | raw file
Possible License(s): MIT
  1. {
  2. * Copyright Š 2011 Dmitriy Zaytsev aka Dim-S
  3. * mail: dz@dim-s.net
  4. * site: http://orion-lang.org
  5. *
  6. * This file is part of OrionLang.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. }
  26. unit ori_vmVariables;
  27. {$ifdef fpc}{$mode delphi}{$endif}
  28. {$H+}
  29. interface
  30. uses
  31. Classes, SysUtils,
  32. ori_StrUtils,
  33. ori_vmTypes,
  34. ori_vmTables,
  35. ori_Types,
  36. ori_Errors,
  37. ori_StrConsts,
  38. ori_Parser,
  39. ori_vmClasses,
  40. ori_vmMemory,
  41. ori_vmGC,
  42. ori_FastArrays,
  43. ori_HashList,
  44. ori_HashMap;
  45. procedure initSGlobalVars();
  46. procedure finalSGlobalVars();
  47. type
  48. TOriVariables = class(TOriTable)
  49. public
  50. function setVariable(const name: MP_String; val: TOriMemory;
  51. ErrPool: TOriErrorPool; const isLink: boolean = false): TOriMemory; overload;
  52. procedure setVariableFromStack(const name: MP_String; val: TOriMemory; const isLink: boolean = false);
  53. function setVariable(const name: MP_String; var cnst: TVMConstant;
  54. aClass: TOriClass; ErrPool: TOriErrorPool; const line: Cardinal): Integer; overload;
  55. function getVariable(const name: MP_String): Integer;
  56. procedure FastClear;
  57. constructor Create;
  58. destructor Destroy; override;
  59. end;
  60. type
  61. POriVarMan = ^TOriVarMan;
  62. TOriVarMan = record
  63. Variables : TOriVariables;
  64. InternalIndex: Integer;
  65. HashCode : Cardinal;
  66. Name : AnsiString;
  67. Next : POriVarMan;
  68. end;
  69. TOriVarManager = class(TPtrArray)
  70. protected
  71. List: THashList;
  72. public
  73. function Get(aVariables: TOriVariables; const HashCode: Cardinal; const Name: AnsiString): POriVarMan;
  74. function GetVar(Item: POriVarMan; aVariables: TOriVariables): TOriMemory;
  75. function GetReVar(Item: POriVarMan; aVariables: TOriVariables): TOriMemory;
  76. procedure Clear;
  77. constructor Create;
  78. end;
  79. var
  80. GlobalVars: TOriVariables;
  81. VarsManager: TOriVarManager;
  82. implementation
  83. uses
  84. ori_ManRes,
  85. ori_vmConstants;
  86. procedure initSGlobalVars();
  87. begin
  88. GlobalVars := TOriVariables.Create;
  89. GlobalVars.Ref_Count := High(Longint)-1;
  90. GlobalVars.GetCreateValue('globals').ValTable(GlobalVars);
  91. end;
  92. procedure finalSGlobalVars();
  93. begin
  94. // --todo
  95. GlobalVars.Delete ( 'globals' );
  96. GlobalVars.Free;
  97. VarsManager.Clear;
  98. end;
  99. function TOriVariables.setVariable(const name: MP_String; val: TOriMemory;
  100. ErrPool: TOriErrorPool; const isLink: boolean = false): TOriMemory;
  101. begin
  102. if isLink then
  103. begin
  104. if not val.IsVarMem then
  105. begin
  106. ErrPool.newError(errFatal, MSG_ERR_NOPTR);
  107. exit;
  108. end;
  109. Result := Self.GetCreate(Name).val;
  110. Result.UnUse;
  111. Result.Typ := mvtPointer;
  112. Result.Mem.ptr := val.AsPtrMemory;
  113. val.Use;
  114. exit;
  115. end else begin
  116. Result := Self.GetCreate(Name).val;
  117. Result.Val(val, false );
  118. end;
  119. Result.UseObject;
  120. end;
  121. procedure TOriVariables.setVariableFromStack(const name: MP_String; val: TOriMemory; const isLink: boolean = false);
  122. var
  123. r: TOriMemory;
  124. begin
  125. val.UseObject;
  126. r := Self.GetCreateValue(Name);
  127. if isLink then
  128. begin
  129. r.Typ := mvtPointer;
  130. r.Mem.ptr := val.AsRealMemory;
  131. val.Use;
  132. exit;
  133. end else
  134. r.Val( val, false );
  135. end;
  136. function TOriVariables.setVariable(const name: MP_String; var cnst: TVMConstant;
  137. aClass: TOriClass; ErrPool: TOriErrorPool; const line: Cardinal): Integer;
  138. var
  139. r: TOriMemory;
  140. id: integer;
  141. x1,x2: MP_String;
  142. m: POriMethod;
  143. xClass: TOriClass;
  144. begin
  145. r := Self.GetCreate(Name).val;
  146. if cnst.typ = mvtWord then
  147. begin
  148. if Pos(defStatic,cnst.str) > 0 then
  149. begin
  150. x1 := ori_StrLower( CopyL(cnst.str,defStatic) );
  151. x2 := CopyR(cnst.str,defStatic);
  152. if x1 = defSelf then
  153. begin
  154. xClass := aClass;
  155. end else if x1 = defParent then
  156. begin
  157. if (aClass = nil) or (aClass.parent = nil) then
  158. begin
  159. xClass := nil;
  160. end else begin
  161. xClass := aClass.parent;
  162. aClass := xClass;
  163. end;
  164. end else
  165. begin
  166. xClass := ori_vmClasses.findByName(x1);
  167. end;
  168. if xClass = nil then
  169. begin
  170. ErrPool.newError(errFatal, MSG_ERR_NO_CLASS_OR_OBJECT, line);
  171. exit;
  172. end;
  173. m := xClass.GetInMethod(x2, aClass);
  174. if (m <> nil) and (m^.typ = omtConst) then
  175. begin
  176. TOriConsts.assignVMConstant(cnst, TOriMemory(m^.ptr));
  177. end else begin
  178. ErrPool.newError(errFatal, Format(MSG_ERR_NO_CLASS_CONST,[x2,x1]), line);
  179. exit;
  180. end;
  181. end else begin
  182. id := ori_vmConstants.VM_Constants.getConstant(cnst.str);
  183. if id <> -1 then
  184. begin
  185. cnst := ori_vmConstants.VM_Constants.Constants[ id ];
  186. end;
  187. end;
  188. end;
  189. r.ValCnst(cnst);
  190. end;
  191. function TOriVariables.getVariable(const name: MP_String): Integer;
  192. begin
  193. Result := byNameIndex(name);
  194. if Result = -1 then
  195. begin
  196. Result := Count;
  197. Add(name, TOriMemory.GetMemory(mvtNull));
  198. end;
  199. end;
  200. { TVariables }
  201. constructor TOriVariables.Create;
  202. begin
  203. inherited;
  204. OrionGC.SetRoot(Self);
  205. end;
  206. destructor TOriVariables.Destroy;
  207. begin
  208. OrionGC.UnsetRoot(Self);
  209. inherited;
  210. end;
  211. procedure TOriVariables.FastClear;
  212. begin
  213. //UnuseObjectAll;
  214. NoneAll;
  215. end;
  216. { TOriVarManager }
  217. procedure TOriVarManager.Clear;
  218. var
  219. i: integer;
  220. item,prev: POriVarMan;
  221. begin
  222. for i := 0 to Count - 1 do
  223. begin
  224. item := Self[ i ];
  225. repeat
  226. prev := item;
  227. item := item.Next;
  228. Dispose(prev);
  229. until item = nil;
  230. end;
  231. inherited Clear;
  232. List.Clear;
  233. end;
  234. constructor TOriVarManager.Create;
  235. begin
  236. inherited Create(100);
  237. List := THashList.Create();
  238. end;
  239. function TOriVarManager.Get(aVariables: TOriVariables; const HashCode: Cardinal;
  240. const Name: AnsiString): POriVarMan;
  241. var
  242. id: integer;
  243. Item: POriVarMan;
  244. begin
  245. id := List.getHashValueCrc(HashCode, Name) - 1;
  246. if id = -1 then
  247. begin
  248. id := Self.Count;
  249. List.setValue(Name, id + 1);
  250. new(Item);
  251. Item.Name := Name;
  252. Item.Variables := aVariables;
  253. Item.Next := nil;
  254. Item.InternalIndex := aVariables.GetCreate(Name).id;
  255. Item.HashCode := HashCode;
  256. Result := Item;
  257. Self.Add( Item );
  258. end else begin
  259. Item := Self[ id ];
  260. Result := Item;
  261. repeat
  262. if Item.Variables = aVariables then
  263. if Item.InternalIndex < aVariables.Count then
  264. with PTableItem(aVariables.Value[Item.InternalIndex].ID)^ do
  265. if (real_crc = HashCode) and (key = Name) then
  266. exit;
  267. if Item.Next = nil then
  268. begin
  269. New(Item.Next);
  270. Item := Item.Next;
  271. Item^.Name := Name;
  272. Item^.Variables := aVariables;
  273. Item^.InternalIndex := aVariables.GetCreate(Name).id;
  274. Item^.HashCode := HashCode;
  275. Item^.Next := nil;
  276. exit;
  277. end;
  278. item := item.Next;
  279. until item = nil;
  280. end;
  281. end;
  282. function TOriVarManager.GetReVar(Item: POriVarMan;
  283. aVariables: TOriVariables): TOriMemory;
  284. var
  285. Origin: POriVarMan;
  286. TableItem: PTableItem;
  287. begin
  288. Origin := Item;
  289. Item := Item.Next;
  290. while Item <> nil do
  291. begin
  292. Dispose(Item);
  293. Item := Item.Next;
  294. end;
  295. Origin.Next := nil;
  296. Origin.Variables := aVariables;
  297. Origin.InternalIndex := aVariables.GetCreate(Origin.Name).id;
  298. Result := aVariables.Values^[ Origin.InternalIndex ];
  299. end;
  300. function TOriVarManager.GetVar(Item: POriVarMan;
  301. aVariables: TOriVariables): TOriMemory;
  302. var
  303. Origin: POriVarMan;
  304. TableItem: PTableItem;
  305. Cnt: Integer;
  306. begin
  307. Origin := Item;
  308. Cnt := 0;
  309. repeat
  310. if Item.Variables = aVariables then
  311. begin
  312. if Item.InternalIndex < aVariables.Count then
  313. begin
  314. Result := aVariables.Values^[ Item.InternalIndex ];
  315. TableItem := PTableItem(Result.ID);
  316. if (TableItem.real_crc = Origin.HashCode) {and (TableItem.key = Origin.Name)} then
  317. begin
  318. exit;
  319. end else begin
  320. Item.InternalIndex := aVariables.GetCreate(Origin.Name).id;
  321. Result := aVariables.Values^[ Item.InternalIndex ];
  322. exit;
  323. end;
  324. end;
  325. end;
  326. if Item.Next = nil then
  327. begin
  328. New(Item.Next);
  329. with Item.Next^ do begin
  330. Variables := aVariables;
  331. InternalIndex := aVariables.GetCreate(Origin.Name).id;
  332. Name := Origin.Name;
  333. HashCode := Origin.HashCode;
  334. Next := nil;
  335. Result := Variables.Values^[ InternalIndex ];
  336. end;
  337. break;
  338. end;
  339. Inc(Cnt);
  340. Item := Item.Next;
  341. if Cnt > 30 then
  342. begin
  343. Result := GetReVar(Origin, aVariables);
  344. exit;
  345. end;
  346. until False;
  347. end;
  348. initialization
  349. VarsManager := TOriVarManager.Create;
  350. end.