Hello,
I have just found wren and quite like it. I'm trying to embed it for a game.
I first embedded lua: the language is too limited, and the syntax is unusual (in particular the way to do pseudo-OO)
I tried to embed python 3: the problem is that it's extremely hard to proevent malicious scripters from doing bad things in their code (i.e. difficult to properly sandbox)
I tried AngelScript: it's quite a good language, but their handle thing is still quite bizarre: sometimes you have to put @, sometimes not; and it's quite hard to register everything right (especially with templates).
Ultimately I wanted to embed V8, because JavaScript is cool and sound for me that getting near to the perfect language ; but I quickly gave up. Their examples in C++ look very cool, but it's way way too difficult to get up and running with something.
So now I found Wren, and it seems to be quite a good fit.
The only real missing feature I have found so far is the ability to save bytecode into a file, because game scripters may don't want to publish their code.
Of course as a newcomer, I have several questions. Here are already a few below.
Thank you for your answers !
1. In the implementation of a foreign method, how can I return an object of another foreign type ?
Wren code:
foreign class Foo { }
foreign class Bar {
foreign foo
}
C code:
struct Foo { };
struct Bar {
Foo* foo;
};
void barGetFoo (WrenVM* vm) {
Bar* bar = (Bar*)wrenGetSlotForeign(vm, 0));
wrenSetSlot???(vm, 0, bar->foo);
}
2. Why can't I write this ?
Is there an alternative ?
Wren code:
foreign class A {}
foreign class B is A {}
3. What about foreign class having multiple constructors ?
Which one should I register in WrenForeignClassMethods.allocate ?
Wren code:
foreign class A {
construct new () {}
construct new (x) {}
}
I have found this workaround, but well... I doubt that it will always be possible to provide simple default values:
Wren code:
foreign class A {
static new () { new(someDefaultValue) }
construct new (x) {}
}
By the way, small language inconsistancy imo:
why the foreign constructor declaration need {}, when all other foreign methods don't ?
Why do we write: construct now () {}
instead of: foreign construct new ()
?
4. In the language, I saw that string conversion wasn't explicit:
Wren code:
var a = "Hello"
var b = 123
var c = a+b // right operant must be a string
OF course I can use b.toString here.
However, is there a way to make string conversion implicit with operator + ? How should I implement it ?
5. More a philosophical than technical question now.
In wren_core.h, I can read this comment:
// With Wren, we try to do as much of it in C as possible. Primitive methods
// are always faster than code written in Wren, and it minimizes startup time
// since we don't have to parse, compile, and execute Wren code.
I totally agreen with you until I see wren_core.wren, with a bunch of core methods implemented in wren.
Why are these methods implemented in wren and not in C ?
Probably that methods like String.join, String.split, etc. could be better implemented in C rather than in Wren.
Additionally, when I see this wren code:
for (element in this) {
if (!first) result = result + sep
first = false
result = result + element.toString
}
I immediately think about the string buffer problem: the fact that the method is going to be slow (complexity O(n^2)).
Hello,
I have just found wren and quite like it. I'm trying to embed it for a game.
I first embedded lua: the language is too limited, and the syntax is unusual (in particular the way to do pseudo-OO)
I tried to embed python 3: the problem is that it's extremely hard to proevent malicious scripters from doing bad things in their code (i.e. difficult to properly sandbox)
I tried AngelScript: it's quite a good language, but their handle thing is still quite bizarre: sometimes you have to put @, sometimes not; and it's quite hard to register everything right (especially with templates).
Ultimately I wanted to embed V8, because JavaScript is cool and sound for me that getting near to the perfect language ; but I quickly gave up. Their examples in C++ look very cool, but it's way way too difficult to get up and running with something.
So now I found Wren, and it seems to be quite a good fit.The only real missing feature I have found so far is the ability to save bytecode into a file, because game scripters may don't want to publish their code.
Of course as a newcomer, I have several questions. Here are already a few below.
Thank you for your answers !1. In the implementation of a foreign method, how can I return an object of another foreign type ?
Wren code:
foreign class Foo { }
foreign class Bar {
foreign foo
}C code:
struct Foo { };
struct Bar {
Foo* foo;
};
void barGetFoo (WrenVM* vm) {
Bar* bar = (Bar*)wrenGetSlotForeign(vm, 0));
wrenSetSlot???(vm, 0, bar->foo);
}
2. Why can't I write this ?
Is there an alternative ?
Wren code:
foreign class A {}
foreign class B is A {}
3. What about foreign class having multiple constructors ?
Which one should I register in WrenForeignClassMethods.allocate ?
Wren code:
foreign class A {
construct new () {}
construct new (x) {}
}
I have found this workaround, but well... I doubt that it will always be possible to provide simple default values:
Wren code:
foreign class A {
static new () { new(someDefaultValue) }
construct new (x) {}
}
By the way, small language inconsistancy imo:
why the foreign constructor declaration need {}, when all other foreign methods don't ?
Why do we write: construct now () {}
instead of: foreign construct new ()
?
4. In the language, I saw that string conversion wasn't explicit:
Wren code:
var a = "Hello"
var b = 123
var c = a+b // right operant must be a string
OF course I can use b.toString here.
However, is there a way to make string conversion implicit with operator + ? How should I implement it ?
5. More a philosophical than technical question now.
In wren_core.h, I can read this comment:
// With Wren, we try to do as much of it in C as possible. Primitive methods
// are always faster than code written in Wren, and it minimizes startup time
// since we don't have to parse, compile, and execute Wren code.I totally agreen with you until I see wren_core.wren, with a bunch of core methods implemented in wren.
Why are these methods implemented in wren and not in C ?
Probably that methods like String.join, String.split, etc. could be better implemented in C rather than in Wren.
Additionally, when I see this wren code:
for (element in this) {
if (!first) result = result + sep
first = false
result = result + element.toString
}
I immediately think about the string buffer problem: the fact that the method is going to be slow (complexity O(n^2)).
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/738b1607-59e2-4106-91bd-886d89bddd4c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hello,
Thank you for your quite quick answers.
Q0:
> An alternative solution would be to encrypt your script, unless Bob
change its mind so we get binary format someday.
OK. Anyway, scripts are already bundled and encrypted in akind of zip
file that may also contain resources (images, sounds, translation
messages, etc.).
Storing bytecode probably takes less space and is faster to load than
source code though.
Q1:
> Because wren don't have control of the lifetime of bar->foo. You have
to wrap foo in an handle to do that.
Can you tell me more on how to do this ?
Can I use wrenSetSlotNewForeign outside of a foreign class allocator ?
If yes: how do I retriev the class object of class named X in C code ?
Q2:
> This is currently forbidden, but might be available in the future. I
think the reason was that it add quite a complexity, and Bob didn't
wanted to go in the rabbit hole without users.
OK. As an alternative I saw that I can overload the is operator. So I
can probably go around the limitation by being smart when registering
methods and by overloading the is operator of the subclass to return
true when called with the superclass.
Or, as you say, by using sort of interfaces.
Q3 (about multiple constructors of a foreign class) :
With your explanations I better understand, thank you. The brackets are
there because in fact that's a normal constructor, I can write any wren
construction code as I wish.
The thing that confused me was that, in the allocator method, I was able
to fetch the parameter passed to the constructor in slot 1. So I though
that the brackets were totally useless and that the actual construction
was the call to my C allocator function (hance my question which
constructor if there are several).
Thank you.
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B58A349.3020609%40quentinc.net.
Hello,
Thank you, I managed to return an object of another foreign type with
your explanations.
Effectively, I need to get first the class slot using wrenGetVariable,
and then use wrenSetSlotNewForeign.
I have now other questions:
I'm now working on basic input type checking, and noticed that
wrenAbortFiber was not working when called inside a foreign method.
Why ? CAn I do something about it ?
I wrote this kind of utility function:
void wrenTypeError (WrenVM* vm, int idx, const char* expectedType) {
char buf[256] = {0};
snprintf(buf, 255, "expected parameter %d to be %s", idx, expectedType);
wrenEnsureSlots(vm, 16);
wrenSetSlotString(vm, 15, buf);
wrenAbortFiber(vm, 15);
}
bool wrenSlotCheckDouble (WrenVM* vm, int slot) {
if (WREN_TYPE_NUM!=wrenGetSlotType(vm, slot)) {
wrenTypeError(vm, slot, "Num");
return false;
}
return true;
}
Used in the following way:
void someForeignMethod (WrenVM* vm) {
if (!wrenSlotCheckDouble(vm, 1)) return;
// do some stuff
}
I also have the problem that, with the base API, I'm not able to check
if a foreign object is really of the expected type, i.e. given foreign
class X {} and foreign class Y {}, there don't seem to have a way to
check in a foreign method if I'm getting an object of type X and not Y.
Isn't there another way than doubling every method like this ?
foreign class X {
foreign someMethod_(x)
someMethod(x){
if (!(x is X)) Fiber.abort("Plouf!")
return someMethod_(x)
}
}
One more question: it is said in the documentation that I shouldn't try
to call wrenCall from inside a foreign method because the VM isn't
reentrant.
What's wrong with it if I save the slots first, like this ?
WrenHandle* callHandle = wrenMakeCallHandle("someMethod()");
int nHandles = wrenGetSlotCount(vm);
WrenHandle* handles[nHandles];
for (int i=0; i<nHandles; i++) handles[i] = wrenGetSlotHandle(vm, i);
wrenSetSlotXXX(vm, 0, methodCallReceiver);
wrenCall(vm, callHandle);
for (int i=0; i<nHandles; i++) {
wrenSetSlotHandle(vm, i, handles[i]);
wrenReleaseHandle(handles[i]);
}
That's enough for now.
Thank you for your answers.
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B5AC491.8060305%40quentinc.net.
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B5C1513.5030606%40quentinc.net.
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B5C95E5.9070102%40quentinc.net.
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B5C95E5.9070102%40quentinc.net.
Le 27/07/2018 à 16:27, QuentinC a écrit :
> Hello,
>
> > It should be working. Maybe you are hitting another bug...
>
> Yes, it was another bug. It found it in the meantime and it works now.
>
> < The problem is not that the API forbid you to do it. I made the VM
> reentrant quite a lots of time. The problem is in the stack management
> and optimisation.
> > I had a lot of discussions with Bob about it, but he don't want to
> change it for now.
> I have lots of pros like architecture cleaning, some simplification in
> the UI/libuv library, but Bob expose the biggest cons with possible
> speed impact(, and maybe usefulness?).
>
> Is there a patch to add reentrancy, or how to proceed to make it ?
I have a patch series, in a branch, but it has to be rebased to master.
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B5CF009.1060901%40quentinc.net.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+unsubscribe@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B5CF009.1060901%40quentinc.net.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/CAAZ5spBTt%3Daa9FoSZqJV0rD192o%3Dk7RS8sn0OsFmiJOnofVU%3Dg%40mail.gmail.com.
While I'm talking about syntax, it may also be nice to add the
following, though it's of course much less important imo (probably in
order of difficulty):
- Allow optional ;
- Allow to declare multiple variables on a single line, e.g. var a=1,
b=2, c=3
- Strings can use " ' or `, e.g. System.print('Hello!')
- Allow any character >=128 to be part of identifier, e.g. var
jeDéveloppeEnFrançais="même si encourager le franglais est un peu dommage"
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B5D477C.3060502%40quentinc.net.
Hello,
Again another question, this one is a little stupid.
How to print a '%' ?
It seems that I'm obliged to write "%("%")".
A bit of a pain. As it was written in the documentation, if '%' isn't
followed by '(', it seemed to be normal, i.e. "%" would print the '%'.
In fact I'm getting an error saying that '%' must be followed by '('.
In my real project I was using %1, %2, etc. to do stuff with
translations, I will have to change it because of that.
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/5B5E86ED.3060607%40quentinc.net.
Cheers,
Bjørn
--
You received this message because you are subscribed to the Google Groups "Wren" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wren-lang+...@googlegroups.com.
To post to this group, send email to wren...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wren-lang/1532969834.812724.1457635984.0A35989E%40webmail.messagingengine.com.