Login
User Name:

Password:



Register
Forgot your password?
Vote for Us!
auth_update crash
Dec 23, 2017, 10:15 pm
By Remcon
check_tumble
Dec 18, 2017, 7:21 pm
By Remcon
parse description bug
Dec 15, 2017, 10:08 pm
By Remcon
Couple bugs
Dec 12, 2017, 5:42 pm
By Remcon
Bug in disarm( )
Nov 12, 2017, 6:54 pm
By GatewaySysop
LoP 1.46
Author: Remcon
Submitted by: Remcon
LOP 1.45
Author: Remcon
Submitted by: Remcon
LOP Heroes Edition
Author: Vladaar
Submitted by: Vladaar
Heroes sound extras
Author: Vladaar
Submitted by: Vladaar
6Dragons 4.3
Author: Vladaar
Submitted by: Vladaar
Users Online
CommonCrawl, Yandex, Majestic-12, Google

Members: 0
Guests: 6
Stats
Files
Topics
Posts
Members
Newest Member
478
3,708
19,242
612
Jacki72H
Today's Birthdays
There are no member birthdays today.
Related Links
» SmaugMuds.org » General » Coding » Kasji's Tiny PHP Implementati...
Forum Rules | Mark all | Recent Posts

Kasji's Tiny PHP Implementation.... for MUDs!
< Newer Topic :: Older Topic > A Better MudProg Solution ;)

Pages:<< prev 1, 2, 3 next >>
Post is unread #41 Jan 5, 2008, 3:25 am
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

Well, actually I meant more than the syntaxes. :wink: I've done my share of Perl too and have come to accept the syntax (it's possible to write nice (well, niceish) Perl, if you work at it). I was referring specifically to embedding it; having done quite a bit of embedding of both the Perl and Lua interpreters, I definitely favor the latter... Embedding Perl always felt like voodoo to me whereas Lua was a breeze. Could be in part the relative simplicity of Lua's API compared to the relative complexity of Perl's, in addition to the much better documentation for Lua than for Perl.
       
Post is unread #42 Jan 5, 2008, 2:33 pm
Go to the top of the page
Go to the bottom of the page

Kasji
Apprentice
GroupMembers
Posts62
JoinedDec 23, 2007

Well it seems altering Lua has proven to be very straight forward.

For example, take this original Lua function:
function foo()
print("hello";)
return
end

I've altered the parser in a few ways, and make note that function foo.bar:something() is not allowed now.
function foo() {
print("hello";);
}

I've also made a return/break statement optional. In the event that a return statement is never found before it reaches the closing curly bracket, it defaults to a return value of zero. That's it for now. I am still looking for what to modify to require variables only to have a '$' in front of them.
       
Post is unread #43 Jan 5, 2008, 8:04 pm
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

Oh... So you altered Lua itself, instead of translating from TinyPHP to Lua? If you wanted to go that way I would have suggested that you use token filters in Lua, without touching the interpreter itself, and let the filters do the syntax handling. Still, it's good that you got this working and are making forward progress. By using Lua's interpreter (disclaimer: or the interpreter from any other embedded scripting language) you are saving yourself heaps upon heaps of time and trouble.

Kasji said:

In the event that a return statement is never found before it reaches the closing curly bracket, it defaults to a return value of zero

So you're not doing TinyPHP exactly, which is good since not having return values makes the language somewhat less useful...

You might want to know though that Lua, by default, returns nil, so if you are really using the Lua interpreter you might want to take that into account to simplify things. That's an important assumption, and depending on where you made your return-statement change, you could be changing things in subtle (and perhaps undesirable) ways.
       
Post is unread #44 Jan 6, 2008, 6:34 pm   Last edited Jan 6, 2008, 6:51 pm by Kasji
Go to the top of the page
Go to the bottom of the page

Kasji
Apprentice
GroupMembers
Posts62
JoinedDec 23, 2007

Thus far all my changes are solely in the parser and lexer source files. It is good to know that by default, Lua returns nil (which I've modified to being NULL for the time being, at least, as far as the token literal goes.) I must be wrong about my prior statement, because what I did was examine the ret_stat function in the parser, which parses the "return" statement, and copied what it does for a return with no expression attached. Essentially, having "return;" is the same as having no return at all.

If I'd known of token filters, I might've gone ahead with that, but since this route is looking good, I'll follow it for now. I have encountered a problem with Lua though. This may be a feature of Lua, but it poses a problem for a PHP syntax. Lua doesn't differentiate between variable symbols and function symbols. Thus:
function foo(x) {
print(x);
return;
}

...

foo = "Something";

Effectively causes you to lose your function symbol, as it is overwritten. This may be a useful thing in Lua, but I need to differentiate between $foo and foo(). When a symbol is registered, whether it be function or variable, both are passed along the same execution path. I still need to study the workings of the symbol table a little more, but what I am considering doing is adding a flag to symbols to differentiate them (if it isn't already there) and differentiate their execution paths, solely for the purpose of parsing $foo and foo differently.

Presently I played with it, adding $ as an optional token, which makes:
$x = 123;
print(x);

The above code possible right now, and it applies to functions as well. You could define a function as foo and call $foo() and it would work. This is my biggest road block. Any advice would be greatly appreciated.

P.S. I'm using Lua 5.1.

Edit: And I never said I was going to stick to the rules in the specification doc I linked to in my initial post. It's more of just a foundation. If a function can't return a value, that essentially makes functions only useful for not having to repeat a particular piece of code over and over. To be honest I didn't initially notice that the specification doc didn't include return statements.

Oh a couple other things I wanted to mention. Multiple assignments in...
LUA:
x,y,z = 1,2,3;
PHP:
$x = 1, $y = 2, $z = 3;

I'm half tempted to keep the Lua syntax because it's less typing. But I want opinions on such a matter. Straying from the TinyPHP specification is fine in some regards, but do you think this is too much? And next, arrays in...
LUA:
a = { this, that, and, more };
PHP:
$a = array(this, that, and, more);

Again, Lua wins for less typing. Thoughts?

The final thing I wish to discuss: In an effort to make this project COTS (component off the shelf,) I believe it would be appropriate to encapsulate the scripting subsystem in an interface. I do have some experience with interfaces, and I really like them, but I am pretty biased.

For those who don't know what an interface is, think of it coupling mechanism between too parts, such as two box cars of a train. The interface allows you to swap out scripting engines without modifying (hopefully) any implementation code in the MU* itself. Interfaces can also be inherited from other interfaces so that you don't have to modify an existing interface to work with any custom code in your MUD, you can inherit from your base interface (say, SmaugFUSS 1.8) and call it whatever and overload or add methods to the interface to accommodate your custom MU* code.
       
Post is unread #45 Jan 6, 2008, 8:34 pm
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

Kasji said:

Essentially, having "return;" is the same as having no return at all.

Yup, that's standard Lua. I actually quite like it. 'nil' in Lua means something interesting, unlike NULL in e.g. C. 'nil' really means "absence of value", not 0. Another interesting thing, which is something of a consequence, is that the only false values in Lua are false and nil. So in particular, zero is not false.

Kasji said:

This may be a useful thing in Lua, but I need to differentiate between $foo and foo().

Indeed in Lua functions are first-class values, so you can mess around with functions just like you would do with normal variables. So in particular, the following code renames the 'print' function:

write = print -- make a copy of print
print = nil -- bam, print no longer means anything


Kasji said:

what I am considering doing is adding a flag to symbols to differentiate them (if it isn't already there) and differentiate their execution paths, solely for the purpose of parsing $foo and foo differently.

If I were you I wouldn't bother. I would enforce that same symbol name --> same value. This is for two reasons:

1. stylistic
I think it is somewhat confusing to have the same name mean different things. I'd not do it even if I could.

2. pragmatic
What you propose sounds like a lot of work with a lot of potential for headache. For me, the gain of being able to use the same symbol name for two things is vastly defeated by the headaches of messing with Lua's internals to the extent of tracing execution paths.

Kasji said:

I'm half tempted to keep the Lua syntax because it's less typing.

Choosing a syntax based on brevity is what leads to monsters like Perl, IMHO. I'd not choose a syntax based on brevity. That said, I would choose a syntax based on simplicity, which is a different notion. And for me, Lua's syntax wins hands down compared to PHP's or Perl's.

In fact, the simplicity of Lua's syntax is the main reason why I think that most everybody here could pick up at least basic Lua very quickly.

All that said, a pragmatic argument for keeping Lua's syntax is that you don't have to do any work whatsoever and can use the entire interpreter right off the shelf. For me this is reason enough to prefer its syntax over another's.

Kasji said:

The final thing I wish to discuss: In an effort to make this project COTS (component off the shelf,) I believe it would be appropriate to encapsulate the scripting subsystem in an interface.

Interfaces are easy for easy things but the more you need them to express the more complex it will get. In particular a scripting engine can be quite complex because you have a lot of stuff going on. You could look at the Active Scripting Interface or whatever it's called -- MUSHclient uses it to talk to several scripting engines. I believe it's Windows-only, though, so that might not be helpful for you.

What I would do is design my code in a modular fashion without explicitly writing an entire interface. I don't know yet if I actually want to swap out one engine for another, and to be honest I probably will never care. However, if I do end up wanting to do so, all the entry points will be cleanly separated anyhow, so while adding a new engine won't be entirely seamless, it would mean only a few days' worth of work. (Assuming the engine itself is relatively easy to embed.)
       
Post is unread #46 Jan 7, 2008, 4:33 pm
Go to the top of the page
Go to the bottom of the page

Kasji
Apprentice
GroupMembers
Posts62
JoinedDec 23, 2007

DavidHaley said:

If I were you I wouldn't bother. I would enforce that same symbol name --> same value. This is for two reasons:

1. stylistic
I think it is somewhat confusing to have the same name mean different things. I'd not do it even if I could.

2. pragmatic
What you propose sounds like a lot of work with a lot of potential for headache. For me, the gain of being able to use the same symbol name for two things is vastly defeated by the headaches of messing with Lua's internals to the extent of tracing execution paths.
Well, the primary reason I am considering this modification is solely to enforce the PHP syntax. In PHP, function names don't begin with $... Variable names do begin with $. Quite frankly, I could care less if a scripter happens to use a function named foo and a variable named $foo. It's not my problem, it's their's. At least, until I have to deal with their sloppy code. Then it becomes double-ly their problem. :)

DavidHaley said:

Choosing a syntax based on brevity is what leads to monsters like Perl, IMHO.
Well, that's more or less what I meant by less typing: simplicity. There really isn't much difference between Lua and PHP in terms of simplicity, but Lua does offer a shorter solution. But I guess I'll just stick with the PHP syntax, regardless of the benefits one way or the other, this project is TinyPHP.

Also, for the idea of interfaces, the primary purpose for them is to make it easier to maintain MUD code, not to swap out engines. Quite frankly at the point, I am willing to write an interface for my own codebase, but I am dreading the thought of having to write one for Smaug FUSS and SWR FUSS. So, I guess we'll see what happens with that. Back to the point of this paragraph though, the interface is meant more as an organizational construct for coders, rather than the modularity that the interface offers. Normally an interface encapsulates a particular system so that you don't have to deal with the internals of the system, but what I am thinking of is more of a two-way interface. Keep the MUD out of the system internals, and keep the system out of the MUD internals, as much as possible.
       
Post is unread #47 Jan 7, 2008, 10:18 pm
Go to the top of the page
Go to the bottom of the page

Kasji
Apprentice
GroupMembers
Posts62
JoinedDec 23, 2007

Well, I figured out an easier way to enforce PHP syntax, via the lexer. Simply put, rather than messing with the symbol table, I've simply added a new token type of VARNAME, which starts with $ and then consists of any letter, number, and underscore. Here's Tiny PHP so far:
function foo($a) {
print($a, type($a));
}

foo("hello";);
foo(123);


Working pretty darn good now. Another problem I encountered though, is that the string concatenation operator in PHP (a single period) is going to be ambiguous in Lua, due to the way the Lua lexer is written. It's going to require some thought, but there needs to be an efficient, simple, or easy way to determine whether a period belongs to a floating point, or it's a concat operator for two strings. Best I can tell is we need to check the previous token, to see if it's a number, if it is, return a decimal token, otherwise if the previous token is a string return a concat operator token, and if the previous token is a variable, well then we need to check the token ahead to see if it's a it's a member element, or if it's another variable or string. If it's a member element, then the period represents a "element selection by reference" operator, otherwise it's a concat operator.
       
Post is unread #48 Jan 8, 2008, 1:39 pm
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

Kasji said:

Well, that's more or less what I meant by less typing: simplicity. There really isn't much difference between Lua and PHP in terms of simplicity,

I don't think we're using the term simplicity in the same way. I was trying to say that I don't mean "less typing" by simplicity, in fact I think that is a dangerous metric for simplicity because again it leads to things like Perl. I view simplicity as corresponding, roughly, to the number of syntactic structures in a language. But I suspect the point isn't terribly relevant so I won't elaborate further.

Kasji said:

Well, I figured out an easier way to enforce PHP syntax, via the lexer. Simply put, rather than messing with the symbol table, I've simply added a new token type of VARNAME, which starts with $ and then consists of any letter, number, and underscore.

Personally I'd be kind of wary of messing with the internal Lua lexer because I wouldn't be sure what effects it would have. But if that's what seems simplest to you, more power to you.

Kasji said:

well then we need to check the token ahead to see if it's a it's a member element, or if it's another variable or string.

Unfortunately, I'm not sure this is even theoretically possible. You won't be able to distinguish between what you call member elements (which are just identifiers) and variables (which are just identifiers). When parsing, you don't even know -- in fact formally you cannot know -- what member elements a table might have due to the dynamic nature of the language. This is why Lua has both '.' and '..' notation: the former for accessing members and the latter for concatenation.
       
Post is unread #49 Jan 8, 2008, 5:53 pm
Go to the top of the page
Go to the bottom of the page

Kasji
Apprentice
GroupMembers
Posts62
JoinedDec 23, 2007

DavidHaley said:

Unfortunately, I'm not sure this is even theoretically possible.
Which leads me to wonder how PHP does it. But I think you're wrong. On the other hand, I could be wrong, but I believe a member element doesn't begin with a $, and thus it is known that it's not an independent variable. Take this psuedo-code as my example:
if (token == '.') {
  switch (prev_token) {
    case NUMBER: // number
      return FP_DECIMAL;
    case STRING: // string
      return CONCAT_OP;
    case NAME: // function or member element
      // If it's a function probably going to have to check to see what it returns. If it returns a string, 
      // we would return CONCAT_OP, if it returns a reference to a class/object, then the period might 
      // be interpreted as a reference to member element. This path is a bit difficult to say.
    case VARNAME: // variable
      switch (next_token) {
        case NAME:
          return REF_MEMBER_ELE;
        case VARNAME:
          return CONCAT_OP;
      }
  }
} 
The above code is far from a complete example, but provides a general quideline for what I am talking about. Some things to note that, if we wanted to make token selection more intelligent, we could try multiple things before deciding on what token to return. Such as in the second switch statement, when we encounter case NAME, we might consider checking to see if that name is a member element of the variable, and then if not, checking to see if NAME is actually a global/local function that returns a string.

Anyhow, I am not extremely concerned with how it would handle different situations, as I wouldn't expect scripters to do far out there things. The concatenation operator is -- in the context of MU*s -- going to be used to form messages to players with variables, such as:
$str = "Hello " . $ch.name . ", how are you?";
Of course at this point I can't say that piece of code is going to be possible, but I will certainly do my best in finding a way to make it happen. And even if certain things aren't possible with it, you can still achieve the end result by breaking the statement up into multiple statements.
       
Post is unread #50 Jan 8, 2008, 6:41 pm
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

Kasji said:

Which leads me to wonder how PHP does it. But I think you're wrong.

I was talking about the Lua framework you are building off of, in which identifiers never start with $. In such a framework, in which variables have no prefix to distinguish them from identifiers in general, my statement is correct.

Kasji said:

Anyhow, I am not extremely concerned with how it would handle different situations, as I wouldn't expect scripters to do far out there things.

Well, this is just me, but I would not want to build a system for which I know there exist rather major problems such as this one, just because those problems are unlikely to occur. The main reason being that Murphy's Law dictates that these problems will eventually occur and give you headaches later on.

Still, the example you gave seems simple enough to handle.
       
Post is unread #51 Jan 8, 2008, 7:26 pm
Go to the top of the page
Go to the bottom of the page

Quixadhal
Conjurer
GroupMembers
Posts398
JoinedMar 8, 2005

Kasji said:

if (token == '.') {
  switch (prev_token) {
    case NUMBER: // number
      return FP_DECIMAL;
    case STRING: // string
      return CONCAT_OP;
    case NAME: // function or member element
      // If it's a function probably going to have to check to see what it returns. If it returns a string, 
      // we would return CONCAT_OP, if it returns a reference to a class/object, then the period might 
      // be interpreted as a reference to member element. This path is a bit difficult to say.
    case VARNAME: // variable
      switch (next_token) {
        case NAME:
          return REF_MEMBER_ELE;
        case VARNAME:
          return CONCAT_OP;
      }
  }
} 


Are you trying to do the lexical parsing and the syntax parsing as one pass, on the fly? The numeric case you have shouldn't normally show up at the syntax level, as the whole token would usually have been gobbled up and thus seeing NUMBER followed by "." would be a CONCAT_OP -- it's up to you if you allow lazy conversion from numbers to strings to allow this to work or not. :)

Remember too, there's nothing saying you HAVE to do this all in one pass. If you do an initial scan for function and type (struct/class) definitions and record their names, your syntax pass would then be able to look up the token and know what kind of thing it is.
       
Post is unread #52 Jan 8, 2008, 8:22 pm
Go to the top of the page
Go to the bottom of the page

Kasji
Apprentice
GroupMembers
Posts62
JoinedDec 23, 2007

Quite frankly, I don't know if it's one pass or not. It's Lua, so whatever Lua is.

You may be right on the number issue, and I don't know if Lua allows lazy conversion from number to string. That psuedo code is merely a way for the lexer to determine the semantics of the period it comes across. Depending on the semantics that the period shows up under, the period can be interpreted as a decimal number, a concatenation operator, or a member element reference operator. I think you are right about the number issue, and I infact have it backwards. A floating point with no leading digits is allowed, such as: .123 so it would need to check and see if the next token is a number, and would then know it's a floating point decimal token. Consider the following semantic examples:
.123
$a.b
$x . "hello"
$a.b . $x
$x . $y
$a.b . $c.d
"hello" . "world"
foo() . $x
foo() . bar()
(get_ref()).mem_ele

There is an extremely large number of possible semantics, and I simply couldn't list every one. How will you know what the period(s) in each example mean? That is the key to solving the concatenation issue of PHP.

Another issue I've come across is dealing with if statements now. Due to the way the parser is written, when an if statement's condition begins, it will keep going and going, even past its supposed parenthesis, until it find a 'then' token.

// Lua:
if (condition) then
// some code
end

// PHP:
if (condition) {
// some code
}

For some reason, when the parser processes condition, it doesn't stop at the last set of parenthesis like it should. The worst part is that a curly bracket has a certain meaning in Lua, and this causes the PHP syntax to not work. I haven't been able to track down the source of this problem entirely yet. But there's gotta be some way to make the condition evaluator to stop when it sees the curly bracket.
       
Post is unread #53 Jan 8, 2008, 9:19 pm
Go to the top of the page
Go to the bottom of the page

Quixadhal
Conjurer
GroupMembers
Posts398
JoinedMar 8, 2005

Kasji said:

There is an extremely large number of possible semantics, and I simply couldn't list every one. How will you know what the period(s) in each example mean? That is the key to solving the concatenation issue of PHP.

You shouldn't need to list every possible combination. I would suggest taking a good look at the flex lexical processor (commonly associated with the bison compiler tool). The idea is, instead of trying to write code to scan text bit-by-bit and hope you catch all the combinations, you write a grammer which describes the language you're trying to implement, and flex then uses that grammer to generate C source which will tokenize it.

Here's a link to the documentation (such that it is). You might also want to check out this grammar, from an alternate php compiler project. Especially the expression section.
       
Post is unread #54 Jan 8, 2008, 9:55 pm   Last edited Jan 8, 2008, 9:56 pm by David Haley
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

Kasji said:

You may be right on the number issue, and I don't know if Lua allows lazy conversion from number to string.

It does, but that doesn't occur during parsing.

Kasji said:

Consider the following semantic examples:

Not to quibble but I think you're misusing the term 'semantic', at least according to how it's typically used in the compilers literature. All this is still syntax.

Kasji said:

Due to the way the parser is written, when an if statement's condition begins, it will keep going and going, even past its supposed parenthesis, (...) For some reason, when the parser processes condition, it doesn't stop at the last set of parenthesis like it should.

Actually, no, it shouldn't be stopping at the closing of the first parenthesis: this is not an error, but intended (and desired) behavior. Lua if conditions are not based on parentheses, but on expressions. It makes perfect sense to go past the first opening parentheses.
if (get_some_function())(arg1, arg2) then
  print("hello";)
end

The whole expression here is a function call. First we get the function returned by get_some_function, and then we call that function with arguments arg1 and arg2.

The simple case is:
if true then
  print("hello";)
end

So no parentheses.

Kasji said:

But there's gotta be some way to make the condition evaluator to stop when it sees the curly bracket.

By this point, I would start reconsidering the approach of messing with Lua's internals, and instead look into using token filters to do syntactic conversion to normal Lua and then let vanilla Lua handle the rest. I am afraid for you that all this dabbling in the internals will be source of much grief later on. Syntactic translation using token filters is likely to make your life easier.
       
Post is unread #55 Jan 9, 2008, 3:58 pm
Go to the top of the page
Go to the bottom of the page

Kasji
Apprentice
GroupMembers
Posts62
JoinedDec 23, 2007


DavidHaley said:


if (get_some_function())(arg1, arg2) then
  print("hello";)
end

The whole expression here is a function call. First we get the function returned by get_some_function, and then we call that function with arguments arg1 and arg2.
Wouldn't this be the same as:
if ( (get_some_function())(arg1, arg2) ) then
  print("hello";)
end
Or am I wrong?
       
Post is unread #56 Jan 9, 2008, 4:03 pm
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

Yes, that is the same, but the point is that grammatically the condition of an if statement is an expression, not a parenthesized expression. It happens that a parenthesized expression is also an expression, but the parentheses are not necessary. This is why the Lua parser doesn't look for parentheses as it's parsing the condition -- it would not be correct to do so.
       
Post is unread #57 Apr 8, 2009, 5:14 pm
Go to the top of the page
Go to the bottom of the page

irbobo
Fledgling
GroupMembers
Posts16
JoinedApr 8, 2009

I love the idea of working with PHP as a scripting language for the MUD. Perhaps a simpler idea would be to shell out and activate the php binary to parse a request then return the results? I'm working on alot of other SMAUG related snippets in PHP and have considered even reprogramming SMAUG in PHP which would be sexy.
       
Post is unread #58 Apr 8, 2009, 8:25 pm
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

Having to spawn a new process every time you wanted to talk to the php would be quite expensive. If it only happens once in a while, it should be fine. But for non-trivial amounts of scripts, it might be too expensive. Anyhow, you'd have to not only spawn the process, but find a way to communicate all necessary information, and it would be quite difficult for the script to ask for more information. Much easier to embed a language IMO.
       
Post is unread #59 Apr 22, 2009, 11:01 pm
Go to the top of the page
Go to the bottom of the page

irbobo
Fledgling
GroupMembers
Posts16
JoinedApr 8, 2009

hmm what about making a converter? like when the mud loads up it'd convert to LUA from PHP?
       
Post is unread #60 Apr 23, 2009, 8:45 am
Go to the top of the page
Go to the bottom of the page

David Haley
Sorcerer
GroupMembers
Posts903
JoinedJan 29, 2007

The general problem of converting code from one language to another is pretty difficult. If you really want to run PHP, you'd be much better off just embedding it. (By the way, it's Lua, not "LUA". It's not an acronym.)
       
Pages:<< prev 1, 2, 3 next >>