diff options
author | David Walter Seikel | 2014-04-01 03:33:04 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-04-01 03:33:04 +1000 |
commit | 068ba885af4b0b1f20e030e0e61df49a436c6b94 (patch) | |
tree | f58c6000ac9ae047d520af30919df69d512c78d2 /ClientHamr | |
parent | Minor clean ups. (diff) | |
download | SledjHamr-068ba885af4b0b1f20e030e0e61df49a436c6b94.zip SledjHamr-068ba885af4b0b1f20e030e0e61df49a436c6b94.tar.gz SledjHamr-068ba885af4b0b1f20e030e0e61df49a436c6b94.tar.bz2 SledjHamr-068ba885af4b0b1f20e030e0e61df49a436c6b94.tar.xz |
Implement Stuff, and module -> parent, plus some clean ups.
Stuff is mostly working, except it's dodging the __index stuff some where in the middle.
So there is debugging stuff all over the place. Thingasm Stuff gets messy sometimes.
Diffstat (limited to 'ClientHamr')
-rw-r--r-- | ClientHamr/GuiLua/skang.lua | 233 | ||||
-rw-r--r-- | ClientHamr/GuiLua/test.lua | 30 |
2 files changed, 155 insertions, 108 deletions
diff --git a/ClientHamr/GuiLua/skang.lua b/ClientHamr/GuiLua/skang.lua index 858a2c8..51e69f2 100644 --- a/ClientHamr/GuiLua/skang.lua +++ b/ClientHamr/GuiLua/skang.lua | |||
@@ -370,23 +370,6 @@ Other Thing things are - | |||
370 | 370 | ||
371 | stuff.s = {a='foo'} -> changes a, deletes everything else, or should. | 371 | stuff.s = {a='foo'} -> changes a, deletes everything else, or should. |
372 | 372 | ||
373 | stuff:stuff('s') -> getmetatable(stuff).__stuff['s'] | ||
374 | |||
375 | stuff.S[key]={...} -> stuff is a Thing, stuff.S is a Thing, stuff.S[key] NOT a Thing. | ||
376 | Unless set up before hand, which it is not since [key] is arbitrary. | ||
377 | We should be re using the same Thing for each [key], but change the Thing.module. | ||
378 | So we copy the Thing from stuff.S when putting stuff into a new [key]. | ||
379 | So the difference is if it's a 'Stuff' or a 'table'. | ||
380 | skang.thing{'S', module=stuff, types='Stuff'} | ||
381 | skang.thing{'field0', module=stuff.S, ...} | ||
382 | skang.thing{'field1', module=stuff.S, ...} | ||
383 | stuff.S is a Thing, it goes through __index and __newindex, so these Things will get caught. | ||
384 | stuff.S[key] = {...} -> __newindex(stuff.S, key, {...}) | ||
385 | if 'Stuff' == modThing.type then | ||
386 | if nil == modThing.__values[key] then rawset(modThing.__values, key, copy(module, key)) | ||
387 | stuff.S[key] = {...} -- Only do this through pairs(), and only put stuff in if it has a matching stuff.S.__stuff | ||
388 | -- Which we do already anyway, so the only change is to copy the Thing? | ||
389 | |||
390 | What we really want is - | 373 | What we really want is - |
391 | squeal.database('db', 'host', 'someDb', 'user', 'password') -> Should return a module. | 374 | squeal.database('db', 'host', 'someDb', 'user', 'password') -> Should return a module. |
392 | local db = require 'someDbThing' -> Same as above, only the database details are encodode in the someDbThing source, OR come from someDbThing.properties. | 375 | local db = require 'someDbThing' -> Same as above, only the database details are encodode in the someDbThing source, OR come from someDbThing.properties. |
@@ -404,7 +387,7 @@ Other Thing things are - | |||
404 | grid.stuff = stuff -> Replace contents of this grid widget with data from all the rows in stuff. | 387 | grid.stuff = stuff -> Replace contents of this grid widget with data from all the rows in stuff. |
405 | choice.stuff = stuff -> As in grid, but only using the keys. | 388 | choice.stuff = stuff -> As in grid, but only using the keys. |
406 | widget.stuff = stuff:stuff('field1') -> This widget gets a particular stufflet. | 389 | widget.stuff = stuff:stuff('field1') -> This widget gets a particular stufflet. |
407 | widget would have to look up getmetatable(window.stuff).module. Or maybe this should work some other way? | 390 | widget would have to look up getmetatable(window.stuff).parent. Or maybe this should work some other way? |
408 | 391 | ||
409 | In all these cases above, stuff is a table that has a Thing metatable, so it has __stuff. | 392 | In all these cases above, stuff is a table that has a Thing metatable, so it has __stuff. |
410 | It is also a Stuff. | 393 | It is also a Stuff. |
@@ -412,7 +395,7 @@ Other Thing things are - | |||
412 | getmetatable(stuff).__keyName | 395 | getmetatable(stuff).__keyName |
413 | getmetatable(stuff).__squeal.where | 396 | getmetatable(stuff).__squeal.where |
414 | And a way to link this database table to others, via the key of the other, as a field in this Stuff. | 397 | And a way to link this database table to others, via the key of the other, as a field in this Stuff. |
415 | stuff:stuff('field0').__link = {module, key, index} | 398 | stuff:stuff('field0').__link = {parent, key, index} |
416 | In Java we had this - | 399 | In Java we had this - |
417 | 400 | ||
418 | public class PersonStuff extends SquealStuff | 401 | public class PersonStuff extends SquealStuff |
@@ -467,6 +450,7 @@ Thing.action = 'nada' -- An optional action to perform. | |||
467 | Thing.tell = '' -- The skang command that created this Thing. | 450 | Thing.tell = '' -- The skang command that created this Thing. |
468 | Thing.pattern = '.*' -- A pattern to restrict values. | 451 | Thing.pattern = '.*' -- A pattern to restrict values. |
469 | 452 | ||
453 | Thing.isStuff = false -- Is this thing a Stuff? | ||
470 | Thing.isReadOnly = false -- Is this Thing read only? | 454 | Thing.isReadOnly = false -- Is this Thing read only? |
471 | Thing.isServer = false -- Is this Thing server side? | 455 | Thing.isServer = false -- Is this Thing server side? |
472 | Thing.isStub = false -- Is this Thing a stub? | 456 | Thing.isStub = false -- Is this Thing a stub? |
@@ -483,36 +467,31 @@ Thing.errors = {} -- A list of errors returned by isValid(). | |||
483 | Thing.__stuff = {} | 467 | Thing.__stuff = {} |
484 | Thing.__values = {} | 468 | Thing.__values = {} |
485 | 469 | ||
486 | Thing.isValid = function (self, module) -- Check if this Thing is valid, return resulting error messages in errors. | 470 | Thing.isValid = function (self, parent) -- Check if this Thing is valid, return resulting error messages in errors. |
487 | -- Anything that overrides this method, should call this super method first. | 471 | -- Anything that overrides this method, should call this super method first. |
488 | local name = self.names[1] | 472 | local name = self.names[1] |
489 | local modThing = getmetatable(module) | 473 | local mumThing = getmetatable(parent) |
490 | local thingy = modThing.__stuff[name] -- TODO - This should be the same as self? | 474 | local value = mumThing.__values[name] |
491 | local key = thingy.names[1]; | ||
492 | local value = modThing.__values[key] | ||
493 | 475 | ||
494 | local t = type(value) or 'nil' | 476 | local t = type(value) or 'nil' |
495 | self.errors = {} | 477 | self.errors = {} |
496 | -- TODO - Naturally there should be formatting functions for stuffing Thing stuff into strings, and overridable output functions. | 478 | -- TODO - Naturally there should be formatting functions for stuffing Thing stuff into strings, and overridable output functions. |
497 | if 'nil' == t then | 479 | if 'nil' == t then |
498 | if self.required then table.insert(self.errors, modThing.names[1] .. '.' .. name .. ' is required!') end | 480 | if self.required then table.insert(self.errors, mumThing.names[1] .. '.' .. name .. ' is required!') end |
499 | else | 481 | else |
500 | if self.types[1] ~= t then table.insert(self.errors, modThing.names[1] .. '.' .. name .. ' should be a ' .. self.types[1] .. ', but it is a ' .. t .. '!') | 482 | if self.types[1] ~= t then table.insert(self.errors, mumThing.names[1] .. '.' .. name .. ' should be a ' .. self.types[1] .. ', but it is a ' .. t .. '!') |
501 | else | 483 | else |
502 | if 'number' == t then value = '' .. value end | 484 | if 'number' == t then value = '' .. value end |
503 | if ('number' == t) or ('string' == t) then | 485 | if ('number' == t) or ('string' == t) then |
504 | if 1 ~= string.find(value, '^' .. self.pattern .. '$') then table.insert(self.errors, modThing.names[1] .. '.' .. name .. ' does not match pattern "' .. self.pattern .. '"!') end | 486 | if 1 ~= string.find(value, '^' .. self.pattern .. '$') then table.insert(self.errors, mumThing.names[1] .. '.' .. name .. ' does not match pattern "' .. self.pattern .. '"!') end |
505 | end | 487 | end |
506 | end | 488 | end |
507 | end | 489 | end |
508 | 490 | ||
509 | local stuff = getmetatable(value) | 491 | for k, v in pairs(self.stuff) do |
510 | if stuff and stuff.__stuff then | 492 | if not v:isValid(value) then |
511 | for k, v in pairs(stuff.__stuff) do | 493 | for i, w in ipairs(v.errors) do |
512 | if not v:isValid(value) then | 494 | table.insert(self.errors, w) |
513 | for i, w in ipairs(v.errors) do | ||
514 | table.insert(self.errors, w) | ||
515 | end | ||
516 | end | 495 | end |
517 | end | 496 | end |
518 | end | 497 | end |
@@ -524,21 +503,21 @@ Thing.remove = function (self) -- Delete this Thing. | |||
524 | end | 503 | end |
525 | 504 | ||
526 | 505 | ||
527 | Thing.__index = function (module, key) | 506 | Thing.__index = function (parent, key) |
528 | -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. | 507 | -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. |
529 | -- TODO - Java skang called isValid() on get(). On the other hand, doesn't seem to call it on set(), but calls it on append(). | 508 | -- TODO - Java skang called isValid() on get(). On the other hand, doesn't seem to call it on set(), but calls it on append(). |
530 | -- Ah, it was doing isValid() on setStufflet(). | 509 | -- Ah, it was doing isValid() on setStufflet(). |
531 | -- TODO - Call thingy.func() if it exists. | 510 | -- TODO - Call thingy.func() if it exists. |
532 | 511 | ||
533 | -- First see if this is a Thing. | 512 | -- First see if this is a Thing. |
534 | local modThing = getmetatable(module) | 513 | local mumThing = getmetatable(parent) |
535 | local thingy | 514 | local thingy |
536 | 515 | ||
537 | if modThing then | 516 | if mumThing and mumThing.self then |
538 | thingy = modThing.__stuff[key] | 517 | thingy = mumThing.self.stuff[key] |
539 | if thingy then | 518 | if thingy then |
540 | local name = thingy.names[1]; | 519 | local name = thingy.names[1]; |
541 | return modThing.__values[name] or thingy.default | 520 | return mumThing.__values[name] or thingy.default |
542 | end | 521 | end |
543 | end | 522 | end |
544 | 523 | ||
@@ -547,37 +526,59 @@ Thing.__index = function (module, key) | |||
547 | return thingy | 526 | return thingy |
548 | end | 527 | end |
549 | 528 | ||
550 | Thing.__newindex = function (module, key, value) | 529 | Thing.__newindex = function (parent, key, value) |
551 | -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. | 530 | -- This only works for keys that don't exist. By definition a value of nil means it doesn't exist. |
552 | local modThing = getmetatable(module) | 531 | local mumThing = getmetatable(parent) |
553 | 532 | ||
554 | if modThing then | 533 | if mumThing and mumThing.self then |
555 | -- This is a proxy table, the values never exist in the real table. In theory. | 534 | -- This is a proxy table, the values never exist in the real table. In theory. |
556 | local thingy = modThing.__stuff[key] | 535 | print('__newindex ' .. mumThing.names[1] .. ' = ' .. key) |
536 | --printTableStart(mumThing, '', 'mumThing') | ||
537 | |||
538 | -- Find the Thing and get it done. | ||
539 | local thingy = mumThing.self.stuff[key] | ||
540 | |||
541 | if not thingy then | ||
542 | -- Deal with setting a new Stuff[key]. | ||
543 | if mumThing.self.isStuff and (nil == mumThing.__values[key]) then | ||
544 | print('__newindex NEW stufflet ' .. key) | ||
545 | rawset(mumThing.__values, key, copy(parent, key)) | ||
546 | --printTableStart(getmetatable(parent).self, '', 'parent thing') | ||
547 | --printTableStart(mumThing.__values[key], '', 'stufflet') | ||
548 | --printTableStart(getmetatable(mumThing.__values[key]), '', 'stufflet metatable?') | ||
549 | --printTableStart(getmetatable(mumThing.__values[key]).self, '', 'stufflet thing?') | ||
550 | mumThing.self.stuff[key] = {names={key}, types={'table'}, parent=mumThing.__values[key], stuff=getmetatable(mumThing.__values[key]).self, } | ||
551 | |||
552 | end | ||
553 | end | ||
554 | |||
557 | if thingy then | 555 | if thingy then |
558 | local name = thingy.names[1] | 556 | local name = thingy.names[1] |
559 | local valueMeta | 557 | local valueMeta |
558 | |||
559 | --printTableStart(thingy, '', 'thingy') | ||
560 | |||
560 | if 'table' == type(value) then | 561 | if 'table' == type(value) then |
561 | -- Coz setting it via modThing screws with the __index stuff somehow. | 562 | -- Coz setting it via mumThing screws with the __index stuff somehow. |
562 | local oldValue = modThing.__values[name] | 563 | local oldValue = mumThing.__values[name] |
563 | if 'table' == type(oldValue) then | 564 | if 'table' == type(oldValue) then |
564 | valueMeta = getmetatable(oldValue) | 565 | valueMeta = getmetatable(oldValue) |
565 | if valueMeta then | 566 | if valueMeta then |
566 | -- TODO - This wont clear out any values in the old table that are not in the new table. Should it? | 567 | -- TODO - This wont clear out any values in the old table that are not in the new table. Should it? |
567 | for k, v in pairs(value) do | 568 | for k, v in pairs(value) do |
568 | local newK = valueMeta.__stuff[k] | 569 | local newK = valueMeta.self.stuff[k] |
569 | if newK then newK = newK.names[1] else newK = k end | 570 | if newK then newK = newK.names[1] else newK = k end |
570 | valueMeta.__values[newK] = v | 571 | valueMeta.__values[newK] = v |
571 | end | 572 | end |
572 | end | 573 | end |
573 | end | 574 | end |
574 | end | 575 | end |
575 | if nil == valueMeta then modThing.__values[name] = value end | 576 | if nil == valueMeta then mumThing.__values[name] = value end |
576 | if 'function' == type(value) then | 577 | if 'function' == type(value) then |
577 | thingy.func = value | 578 | thingy.func = value |
578 | else | 579 | else |
579 | -- NOTE - invalid values are still stored, this is by design. | 580 | -- NOTE - invalid values are still stored, this is by design. |
580 | if not thingy:isValid(module) then | 581 | if not thingy:isValid(parent) then |
581 | for i, v in ipairs(thingy.errors) do | 582 | for i, v in ipairs(thingy.errors) do |
582 | print('ERROR - ' .. v) | 583 | print('ERROR - ' .. v) |
583 | end | 584 | end |
@@ -589,7 +590,7 @@ Thing.__newindex = function (module, key, value) | |||
589 | end | 590 | end |
590 | end | 591 | end |
591 | 592 | ||
592 | rawset(module, key, value) -- Stuff it normally. | 593 | rawset(parent, key, value) -- Stuff it normally. |
593 | end | 594 | end |
594 | 595 | ||
595 | Thing.__call = function (func, ...) | 596 | Thing.__call = function (func, ...) |
@@ -608,12 +609,12 @@ The first argument can be another Thing (the parent), or a string list of names | |||
608 | It can be called by itself, with no parent specified - | 609 | It can be called by itself, with no parent specified - |
609 | thingasm('foo', 'help text) | 610 | thingasm('foo', 'help text) |
610 | 611 | ||
611 | In this case the surrounding Lua environment becomes the module of foo. | 612 | In this case the surrounding Lua environment becomes the parent of foo. |
612 | If the first argument (or first in the table) is a string, then it's this form. | 613 | If the first argument (or first in the table) is a string, then it's this form. |
613 | All others include the module as the first argument, which would be a table. | 614 | All others include the parent as the first argument, which would be a table. |
614 | 615 | ||
615 | It can be called by calling the parent as a function - | 616 | It can be called by calling the parent as a function - |
616 | foo('bar', 'some help', types='table') -- ___call(foo, 'bar', ...) And now foo is the module. | 617 | foo('bar', 'some help', types='table') -- ___call(foo, 'bar', ...) And now foo is the parent. |
617 | foo.bar{'baz', types='Stuff'} -- thingasm({foo.bar, 'baz', ...}) | 618 | foo.bar{'baz', types='Stuff'} -- thingasm({foo.bar, 'baz', ...}) |
618 | foo.bar.baz{'field0'} -- thingasm({foo.bar.baz, 'field0'}) | 619 | foo.bar.baz{'field0'} -- thingasm({foo.bar.baz, 'field0'}) |
619 | foo.bar.baz{'field1'} | 620 | foo.bar.baz{'field1'} |
@@ -625,21 +626,21 @@ It can be called by calling the parent as a function - | |||
625 | thingasm = function (names, ...) | 626 | thingasm = function (names, ...) |
626 | local params = {...} | 627 | local params = {...} |
627 | local new = false | 628 | local new = false |
628 | local module | 629 | local parent |
629 | 630 | ||
630 | -- Check how we were called, and re arrange stuff to match. | 631 | -- Check how we were called, and re arrange stuff to match. |
631 | if 0 == #params then | 632 | if 0 == #params then |
632 | if ('table' == type(names)) then -- thingasm{...} | 633 | if ('table' == type(names)) then -- thingasm{...} |
633 | params = names | 634 | params = names |
634 | names = shiftLeft(params) | 635 | names = shiftLeft(params) |
635 | if 'table' == type(names) then -- thingasm{module, 'foo', ...} | 636 | if 'table' == type(names) then -- thingasm{parent, 'foo', ...} |
636 | module = names | 637 | parent = names |
637 | names = shiftLeft(params) | 638 | names = shiftLeft(params) |
638 | end | 639 | end |
639 | end -- thingasm("foo") otherwise | 640 | end -- thingasm("foo") otherwise |
640 | else | 641 | else |
641 | if 'table' == type(names) then | 642 | if 'table' == type(names) then |
642 | module = names | 643 | parent = names |
643 | if 'string' == type(...) then params = {...} -- C or __call(table, string, ..) | 644 | if 'string' == type(...) then params = {...} -- C or __call(table, string, ..) |
644 | elseif 'table' == type(...) then params = ... -- __call(table, table) | 645 | elseif 'table' == type(...) then params = ... -- __call(table, table) |
645 | end | 646 | end |
@@ -654,33 +655,33 @@ thingasm = function (names, ...) | |||
654 | 655 | ||
655 | -- TODO - Double check this comment - No need to bitch and return if no names, this will crash for us. | 656 | -- TODO - Double check this comment - No need to bitch and return if no names, this will crash for us. |
656 | 657 | ||
657 | -- Grab the environment of the calling function if no module was passed in. | 658 | -- Grab the environment of the calling function if no parent was passed in. |
658 | module = module or getfenv(2) | 659 | parent = parent or getfenv(2) |
659 | local modThing = getmetatable(module) | 660 | local mumThing = getmetatable(parent) |
660 | if nil == modThing then | 661 | if nil == mumThing then |
661 | modThing = {} | 662 | mumThing = {} |
662 | -- This is how the Thing is stored with the module. | 663 | mumThing.self = {stuff={}} |
663 | setmetatable(module, modThing) | 664 | setmetatable(parent, mumThing) |
664 | end | 665 | end |
665 | -- Coz at module creation time, Thing is an empty table, and setmetatable(modThing, {__index = Thing}) doesn't do the right thing. | 666 | -- Coz at module creation time, Thing is an empty table, and setmetatable(mumThing, {__index = Thing}) doesn't do the right thing. |
666 | -- Also, module might not be an actual module, this might be Stuff. | 667 | if nil == mumThing.__values then |
667 | if nil == modThing.__stuff then | ||
668 | -- Seems this does not deal with __index and __newindex, and also screws up __stuff somehow. | 668 | -- Seems this does not deal with __index and __newindex, and also screws up __stuff somehow. |
669 | -- setmetatable(modThing, {__index = Thing}) | 669 | -- setmetatable(mumThing, {__index = Thing}) |
670 | modThing.names = {module._NAME or 'NoName'} | 670 | mumThing.names = {parent._NAME or 'NoName'} |
671 | modThing.__stuff = {} | 671 | if parent._NAME then mumThing.types = {'Module'} end |
672 | modThing.__values = {} | 672 | mumThing.__values = {} |
673 | modThing.__index = Thing.__index | 673 | mumThing.__index = Thing.__index |
674 | modThing.__newindex = Thing.__newindex | 674 | mumThing.__newindex = Thing.__newindex |
675 | end | 675 | end |
676 | 676 | ||
677 | local thingy = modThing.__stuff[name] | 677 | local thingy = mumThing.self.stuff[name] |
678 | if not thingy then -- This is a new Thing. | 678 | if not thingy then -- This is a new Thing. |
679 | new = true | 679 | new = true |
680 | thingy = {} | 680 | thingy = {} |
681 | thingy.module = module | ||
682 | thingy.names = names | 681 | thingy.names = names |
683 | setmetatable(thingy, {__index = Thing}) -- To pick up isValid, pattern, and the other stuff. | 682 | thingy.parent = parent |
683 | thingy.stuff = {} | ||
684 | setmetatable(thingy, {__index = Thing}) -- To pick up isValid, pattern, and the other stuff by default. | ||
684 | end | 685 | end |
685 | 686 | ||
686 | -- Pull out positional arguments. | 687 | -- Pull out positional arguments. |
@@ -695,13 +696,13 @@ thingasm = function (names, ...) | |||
695 | elseif 'names' == k then | 696 | elseif 'names' == k then |
696 | oldNames = thingy.names | 697 | oldNames = thingy.names |
697 | thingy.names = cvs2table(v) | 698 | thingy.names = cvs2table(v) |
699 | elseif 'required' == k then | ||
700 | if isBoolean(v) then thingy.required = true end | ||
698 | else thingy[k] = v | 701 | else thingy[k] = v |
699 | end | 702 | end |
700 | end | 703 | end |
701 | end | 704 | end |
702 | 705 | ||
703 | thingy.required = isBoolean(thingy.required) | ||
704 | |||
705 | -- Find type, default to string, then break out the other types. | 706 | -- Find type, default to string, then break out the other types. |
706 | local typ = type(thingy.default) | 707 | local typ = type(thingy.default) |
707 | if 'nil' == typ then typ = 'string' end | 708 | if 'nil' == typ then typ = 'string' end |
@@ -709,67 +710,87 @@ thingasm = function (names, ...) | |||
709 | if '' == types then types = typ end | 710 | if '' == types then types = typ end |
710 | thingy.types = csv2table(types) | 711 | thingy.types = csv2table(types) |
711 | 712 | ||
712 | if ('Stuff' == thingy.types[1]) or ('table' == thingy.types[1]) then | 713 | if 'Stuff' == thingy.types[1] then |
714 | thingy.types[1] = 'table' | ||
715 | thingy.isStuff = true | ||
716 | end | ||
717 | if 'table' == thingy.types[1] then | ||
713 | if '' == thingy.default then thingy.default = {} end | 718 | if '' == thingy.default then thingy.default = {} end |
714 | setmetatable(thingy.default, {__call = Thing.__call}) | 719 | setmetatable(thingy.default, |
720 | { | ||
721 | self = thingy, | ||
722 | parent = parent, | ||
723 | names = names, | ||
724 | __values = {}, | ||
725 | __index = Thing.__index, | ||
726 | __newindex = Thing.__newindex, | ||
727 | __call = Thing.__call, | ||
728 | }) | ||
715 | end | 729 | end |
716 | 730 | ||
717 | -- Remove old names, then stash the Thing under all of it's new names. | 731 | -- Remove old names, then stash the Thing under all of it's new names. |
718 | for i, v in ipairs(oldNames) do | 732 | for i, v in ipairs(oldNames) do |
719 | modThing.__stuff[v] = nil | 733 | mumThing.self.stuff[v] = nil |
720 | end | 734 | end |
721 | for i, v in ipairs(thingy.names) do | 735 | for i, v in ipairs(thingy.names) do |
722 | modThing.__stuff[v] = thingy | 736 | mumThing.self.stuff[v] = thingy |
723 | end | 737 | end |
724 | 738 | ||
725 | -- This triggers the Thing.__newindex metamethod above. If nothing else, it triggers thingy.isValid() | 739 | -- This triggers the Thing.__newindex metamethod above. If nothing else, it triggers thingy.isValid() |
726 | if new then module[name] = thingy.default end | 740 | if new and not mumThing.self.isStuff then parent[name] = thingy.default end |
727 | end | 741 | end |
728 | 742 | ||
729 | 743 | ||
730 | fixNames = function (module, name) | 744 | fixNames = function (module, name) |
731 | local stuff = getmetatable(module) | 745 | local stuff = getmetatable(module) |
732 | stuff.names[1] = name | 746 | if stuff then |
733 | for k, v in pairs(stuff.__stuff) do | 747 | stuff.names[1] = name |
734 | if 'table' == v.types[1] then | 748 | for k, v in pairs(stuff.self.stuff) do |
735 | local name = v.names[1] | 749 | if 'table' == v.types[1] then |
736 | print(name .. ' -> ' .. name) | 750 | local name = v.names[1] |
737 | fixNames(stuff.__values[name], name) | 751 | print(name .. ' -> ' .. name) |
752 | fixNames(stuff.__values[name], name) | ||
753 | end | ||
738 | end | 754 | end |
739 | end | 755 | end |
740 | end | 756 | end |
741 | 757 | ||
742 | 758 | ||
743 | copy = function (module, name) | 759 | copy = function (parent, name) |
744 | local result = {} | 760 | local result = {} |
745 | local thingy = {} | 761 | local stuff = getmetatable(parent).self.stuff |
746 | local modThing = getmetatable(module) | ||
747 | |||
748 | for k, v in pairs(Thing) do | ||
749 | thingy[k] = v | ||
750 | end | ||
751 | 762 | ||
752 | thingy.__values = {} | 763 | for k, v in pairs(stuff) do |
753 | for k, v in pairs(modThing.__values) do | 764 | local temp = {} |
754 | thingy.__values[k] = v | 765 | for l, w in pairs(v) do |
766 | temp[l] = w | ||
767 | end | ||
768 | temp[1] = table.concat(temp.names, ',') | ||
769 | temp.names = nil | ||
770 | temp.types = table.concat(temp.types, ',') | ||
771 | temp.errors = nil | ||
772 | temp.parent = nil | ||
773 | thingasm(result, temp) | ||
755 | end | 774 | end |
775 | getmetatable(result).names = {name} | ||
756 | 776 | ||
757 | thingy.__stuff = modThing.__stuff | 777 | -- TODO - Should we copy values to? |
758 | thingy.module = result | ||
759 | thingy.names = {name} | ||
760 | setmetatable(thingy, {__index = Thing}) | ||
761 | setmetatable(result, thingy) | ||
762 | 778 | ||
763 | return result | 779 | return result |
764 | end | 780 | end |
765 | 781 | ||
766 | 782 | ||
783 | stuff = function (aThingy, aStuff) | ||
784 | return getmetatable(aThingy).self.stuff[aStuff] | ||
785 | end | ||
786 | |||
787 | |||
767 | get = function (stuff, key, name) | 788 | get = function (stuff, key, name) |
768 | local result | 789 | local result |
769 | if name then | 790 | if name then |
770 | local thingy = getmetatable(stuff) | 791 | local thingy = getmetatable(stuff) |
771 | if thingy then | 792 | if thingy then |
772 | local this = thingy.__stuff[key] | 793 | local this = thingy.self.stuff[key] |
773 | if this then result = this[name] end | 794 | if this then result = this[name] end |
774 | end | 795 | end |
775 | else | 796 | else |
@@ -783,7 +804,7 @@ reset = function (stuff, key, name) | |||
783 | if name then | 804 | if name then |
784 | local thingy = getmetatable(stuff) | 805 | local thingy = getmetatable(stuff) |
785 | if thingy then | 806 | if thingy then |
786 | local this = thingy.__stuff[key] | 807 | local this = thingy.self.stuff[key] |
787 | if this then this[name] = nil end | 808 | if this then this[name] = nil end |
788 | end | 809 | end |
789 | else | 810 | else |
@@ -796,7 +817,7 @@ set = function (stuff, key, name, value) | |||
796 | if 'nil' ~= type(value) then | 817 | if 'nil' ~= type(value) then |
797 | local thingy = getmetatable(stuff) | 818 | local thingy = getmetatable(stuff) |
798 | if thingy then | 819 | if thingy then |
799 | local this = thingy.__stuff[key] | 820 | local this = thingy.self.stuff[key] |
800 | if this then this[name] = value end | 821 | if this then this[name] = value end |
801 | end | 822 | end |
802 | else | 823 | else |
diff --git a/ClientHamr/GuiLua/test.lua b/ClientHamr/GuiLua/test.lua index 636090e..34b1a56 100644 --- a/ClientHamr/GuiLua/test.lua +++ b/ClientHamr/GuiLua/test.lua | |||
@@ -127,6 +127,9 @@ skang.thingasm{stuff.t, 'c', 'Another sub stufflet'} | |||
127 | skang.thingasm{stuff, 's', 'A Stuff', types='table'} | 127 | skang.thingasm{stuff, 's', 'A Stuff', types='table'} |
128 | stuff.s{'sa,a', 'A stufflet in a Stuff'} | 128 | stuff.s{'sa,a', 'A stufflet in a Stuff'} |
129 | stuff.s{'sb,b', 'Another stufflet in a Stuff'} | 129 | stuff.s{'sb,b', 'Another stufflet in a Stuff'} |
130 | skang.thingasm{stuff, 'S', 'A database table of Stuff', types='Stuff'} | ||
131 | stuff.S{'field0', 'The first field of the db table.'} | ||
132 | stuff.S{'field1', 'The second field of the db table.'} | ||
130 | 133 | ||
131 | print('*********************************') | 134 | print('*********************************') |
132 | skang.fixNames(skang, 'skang') | 135 | skang.fixNames(skang, 'skang') |
@@ -141,10 +144,11 @@ print(skang.get(stuff.t, 'c', 'help')) | |||
141 | print(skang.get(stuff, 's', 'help')) | 144 | print(skang.get(stuff, 's', 'help')) |
142 | print(skang.get(stuff.s, 'sa', 'help')) | 145 | print(skang.get(stuff.s, 'sa', 'help')) |
143 | print(skang.get(stuff.s, 'sb', 'help')) | 146 | print(skang.get(stuff.s, 'sb', 'help')) |
147 | print(skang.get(stuff.S, 'field0', 'help')) | ||
148 | print(skang.get(stuff.S, 'field1', 'help')) | ||
144 | skang.thingasm{test, 'baz,b', 'A test stufflet for test'} | 149 | skang.thingasm{test, 'baz,b', 'A test stufflet for test'} |
145 | print(skang.get(test, 'b', 'help')) | 150 | print(skang.get(test, 'b', 'help')) |
146 | print(skang.get(test, 'f', 'help')) | 151 | print(skang.get(test, 'f', 'help')) |
147 | --skang.printTableStart(getmetatable(stuff.s), '', 'stuff.s metatable') | ||
148 | -- Should fail isValid() | 152 | -- Should fail isValid() |
149 | stuff.a = 1 | 153 | stuff.a = 1 |
150 | stuff.t.b = '2' | 154 | stuff.t.b = '2' |
@@ -161,6 +165,12 @@ stuff.s.b = 33 | |||
161 | stuff.s = {a=8, sb='9'} | 165 | stuff.s = {a=8, sb='9'} |
162 | stuff.s.sb = 44 | 166 | stuff.s.sb = 44 |
163 | print('') | 167 | print('') |
168 | --stuff.S.record0 = {} | ||
169 | stuff.S.record0 = {field0=0, field1='zero'} | ||
170 | --stuff.S['record1'] = {field0='1', field1='one'} | ||
171 | --stuff.S['record2'] = {field0='2', field1='two'} | ||
172 | |||
173 | print('') | ||
164 | 174 | ||
165 | print(skang.get(stuff, 'a')) | 175 | print(skang.get(stuff, 'a')) |
166 | print(skang.get(stuff.t, 'b')) | 176 | print(skang.get(stuff.t, 'b')) |
@@ -189,4 +199,20 @@ print(test_c.c) | |||
189 | print(test_c.cfooble) | 199 | print(test_c.cfooble) |
190 | print(stuff.s.sa) | 200 | print(stuff.s.sa) |
191 | print(stuff.s.sb) | 201 | print(stuff.s.sb) |
192 | skang.printTableStart(stuff.s, '', 'stuff.s') | 202 | --skang.printTableStart(stuff.s, '', 'stuff.s') |
203 | print('') | ||
204 | |||
205 | --skang.printTableStart(stuff.S, '', 'stuff.S') | ||
206 | |||
207 | print(stuff.S['record0'].field1) | ||
208 | --print(stuff.S['record1'].field1) | ||
209 | --print(stuff.S['record2'].field0) | ||
210 | |||
211 | --skang.printTableStart(stuff.S['record0'], '', 'stuff.S[record0]') | ||
212 | --skang.printTableStart(stuff.S['record1'], '', 'stuff.S[record1]') | ||
213 | --skang.printTableStart(stuff.S['record2'], '', 'stuff.S[record2]') | ||
214 | |||
215 | --skang.printTableStart(getmetatable(stuff.s), '', 'stuff.s metatable') | ||
216 | --skang.printTableStart(getmetatable(stuff), '', 'stuff metatable') | ||
217 | --skang.printTableStart(getmetatable(stuff.S), '', 'stuff.S metatable') | ||
218 | --skang.printTableStart(skang.stuff(stuff, 'S'), '', 'stuff.S Thing') | ||