MiniC - a small language written in Monkey

Monkey Forums/User Modules/MiniC - a small language written in Monkey

Risc(Posted 2012) [#1]
I've written a small, typeless C-like language in Monkey. It embeds easily into existing Monkey code and it's fast.

Since it's written in Monkey, it does not depend on any external libraries and should compile to all targets without any modifications.

I've released it under the LGPL so you're free to integrate it into commercial software. However any changes you make to MiniC itself must be made publicly available so others may benefit from it.

The code can be found on bitbucket here:

Have fun!

EDIT: typos

Shinkiro1(Posted 2012) [#2]
Sounds interesting.
Is there a way to download it if I'm not registered at bitbucket?

DruggedBunny(Posted 2012) [#3]
If you can download via Mercurial/Hg, the no-signup link is here:

Haven't tried it yet but it does indeed sound interesting!

Samah(Posted 2012) [#4]
Very nice. I'm still fighting with Lua... I've (mostly) implemented a pure Monkey Lua 5.1 VM, but I think it will be abysmally slow. My MonkeyLua wrapper only works on C++ supported targets at the moment since it's externed rather than pure Monkey.

Shinkiro1(Posted 2012) [#5]
Thanks DruggedBunny.
I have just looked at the source and this looks really nice, very clean code :)
Now waiting for more examples.

Risc(Posted 2012) [#6]
I didn't know that you had to be registered in order to read the wiki/download the code. That's crap. If that is the case I'll probably move it to gitHub instead.

@Shinkiro1: Thanks :) Here's an example (also available on the wiki):

EDIT: Removed the example code so I don't have to update BOTH the wiki and this post every time I make a change. So from now on refer to the wiki for reference (link in first post).

slenkar(Posted 2012) [#7]
i wanna ask you a bunch of questions

how similar is it to c?
where is the wiki?
does it have structs?

Risc(Posted 2012) [#8]
@slenkar: It's as similar to C as what you see in the example above. In fact, that is all statements supported.

It doesn't have structs and probably never will. If anything it's probably more similar to Javascript than C. The next version I'm working on will have a way to interface with scopes, so you can write something like:

animal = func(name){
   roar = func(){
      print(name + ' roars!');
   return this;

monkey = animal('Baloo');
cat = animal('Kitty');

monkey.roar(); //Would print Baloo roars!
cat.roar(); //Would print Kitty roars!

The link in the top post points to the wiki.

Goodlookinguy(Posted 2012) [#9]
I think you have the wiki set to private, even when logged in it says I don't have permission to view it.

Also, great job with this. I've been having fun live loading tests. One thing that's been bugging me, and maybe it's just a personal preference thing, but all Monkey strings must be in double quotes. It's unusual feeling to suddenly switch to using only single quotes. I used double quotes and it gave me an error related to the semi-colon which threw me off.

Edit: Using your example above, using an else statement causes the parser to fail. An if statement without an else seems to work fine.

Edit Again: Nevermind, it seems to be issues in general parsing if statements. Especially within function blocks.

Edit Again Again: It seems to be issues specifically related to the equality operator ==

Likely Last Edit: There's several ways you could be optimizing your code.
[monkeycode]If left.dataFloat = right.dataFloat
Return VMValue.CreateFloat(1)
Return VMValue.CreateFloat(0)

I'm seeing this a lot and you could simplify it by explicity casting the boolean to an integer as shown below.

Return VMValue.CreateFloat(Int(left.dataFloat = right.dataFloat))

Last Edit... I think I might fork from your version as I've fixed the problem above and have added some missing tokens.

Goodlookinguy(Posted 2012) [#10]
*forum copied my edited post...*

Risc(Posted 2012) [#11]
Yes there are a couple of known bugs in the parser regarding the if-else statement. The else-statement currently does not work, and there is an issue describing it in the repository. (EDIT: fixed and pushed the else-bug). I actually mistyped my example, you don't compare with ==, you compare with =

Thanks for the code suggestion but I like it the way it is since I think it's a bit more readable than what you posted.

Fork away, remember to issue a pull request if you fix a bug or introduce something interesting :)

Risc(Posted 2012) [#12]
Ok so I also replaced the equality comparer '=' with '==' to mimic C-style expressions. I kept mistyping the thing and @Goodlookingguy's post made it clear that this needed to be changed.

Will update my post above.

Goodlookinguy(Posted 2012) [#13]
I fixed a recursive reader bug but, I'm not sure if you want to take all of the code I've added. I added double quotes and escaping because C supports both single and double quotes, so it seems right to me. I also added external function value returning and an adapter for the IVMDelegate interface. As well as a not equal to operator (!=) and string comparisons.

Link to changes:

Risc(Posted 2012) [#14]
@Goodlookingguy: Nice :) Looks like you fixed issue #1 ( Please issue a pull request for this fix so it can be traced back to you.

Good work with the != operator too :) Please, if you don't mind, update the EBNF at the wiki to reflect this change. This makes it easier to maintain the language.

However I don't quite see the point of your IVMDelegateN interface and adapter? Could you please elaborate on this.

Goodlookinguy(Posted 2012) [#15]
The issue tracker on MiniC is private so I couldn't see that issue.

However I don't quite see the point of your IVMDelegateN interface and adapter? Could you please elaborate on this.

The adapter is for old code that's still using IVMDelegate. To ensure that it still compiles. It's for backwards compatibility. If you're not too worried about breaking compatibility then the IVMDelegate interface can be replaced with the other one.

Edit: I should note that the N at the end of IVMDelegateN doesn't stand for anything. I have a tendency to write a capital letter, typically N, when I'm not 100% sure what's going to be done with a certain piece of code, like this.

Risc(Posted 2012) [#16]
Allright made the issue tracker public. You should be able to see it now. Don't worry about breaking old code right now since no stable version has been released yet.

Goodlookinguy(Posted 2012) [#17]
I removed all of the compatibility stuff, updated the examples plus a new example using mojo, and updated the pull request.

Risc(Posted 2012) [#18]
Great work :) Pull request accepted and merged in main branch.

Haven't tested your mojo-example yet, how does it perform? To be honest I haven't run any benchmarks on MiniC yet.

Goodlookinguy(Posted 2012) [#19]
I was running it at 30FPS on GLFW and was getting 30FPS, so it's at least fast enough to perform what I have it doing in that test.

Risc(Posted 2012) [#20]
Nice. That's pretty much what I expected.

Goodlookinguy(Posted 2012) [#21]
I spent the last 10 hours creating delegates from the main monkey and mojo module for pretty much everything that can be accessed via non-OOP ways. This should speed up testing hassles and improve general usage or at least I hope it will.

I also changed the identifier scanner so that it supports A-Z, a-z, _, and 0-9 after the first character of the identifier. I had to do this because of functions like atan2.

Risc(Posted 2012) [#22]
Saw your pull request. Will examine it when I get home from work.

Risc(Posted 2012) [#23]
Ok I investigated your pull request and I'm going to approve the identifier code. However, I realize how much time and work you've invested in the mojo-bindings and I can't say I'm not impressed, but at the moment it does not fit in the main MiniC branch. Thing is, I want to keep the codebase small and basically the main target for MiniC scripts is general scripting, most likely gameplay elements. I do not want to promote MiniC as a way of creating games. Monkey is already perfect for that.

Now, with that said, it would be perfect as an add-on to MiniC when this functionality is required. But I don't know how we would host that, yet.

Samah(Posted 2012) [#24]
I'm going to fork this and hopefully throw you some pull requests. :)
So far I've got expression lists mostly working. This means multiple return values :D

Edit: It works!
foo = func() {
  return 1, 2, 3;

a,b,c = foo();


Edit 2: This also works!
foo = func() {
  return 1, 2, 3;
bar = func() {
  return 4, 5;
a,b,c,d,e = foo(),bar();

And it expands foo(),bar() to be 5 values.

Samah(Posted 2012) [#25]
I'm continuing to merge my fork, so if anyone wants unofficial features, they can try mine.

Rhodesy(Posted 2012) [#26]
Really interesting module, i have a question or two... do you plan on adding arrays to this? And more statements like "select" ?

Rhodesy(Posted 2012) [#27]
Does this allow for the following:

a = func(b) { return b+1; }

Goodlookinguy(Posted 2012) [#28]
Yes, but don't forget to add a semi-colon after the function definition brackets.

a = func(b)
    return b+1;
}; // <--


Rhodesy(Posted 2012) [#29]
Ok, I figured out I was always using dataStr of the params.....

Got a more robust print delegate method now.

Goodlookinguy(Posted 2012) [#30]
If you're looking for common functions and such you might want to look at the bindings I created. . It already had the float to string for printing as well as a ton more.

Rhodesy(Posted 2012) [#31]
I've been extending this a bit with a simple array / collection system, its half working at the moment. Any plans to add this functionality yourself?

Rhodesy(Posted 2012) [#32]
Been playing a bit more with this...
getIndex = func(index) {
	return index;

a = [53,['Hello there.',324,[7,6,5,4]],12];


As expected, returns:
print: Hello there.
print: 324
print: Collection

Thinking about more, I think I'll be changing this into hashes instead of just arrays/collections.

Risc(Posted 2012) [#33]
Rhodesy: For the moment, there are no plans to support arrays/collections.

Landon(Posted 2013) [#34]
Right on this is more than adequate for a simple script system for an rpg game i am working on.

Goodlookinguy(Posted 2013) [#35]
For anyone interested I've been fixing, updating, and upgrading the capabilities of MiniC for some time now. While it seems like the project leader stopped, I'm still going. My version includes operator overloading capabilities now as well as the negation operator working. You can get it here I plan on adding quite a bit more, but am just barely getting around it. I suppose it's not really as MiniC was intended at this point, but I think the changes I'm adding make it more robust. Especially for what I need it for.

I've also added array capabilities without modifying MiniC itself in my MiniC Common Bindings, found here

Shinkiro1(Posted 2013) [#36]
Thanks Goodlookingguy, I have had my eyes on minic a long time and it's great to hear it's still actively developed.

therevills(Posted 2013) [#37]
Excellent - MiniC was a very good idea.

Have you considered Samah's folk with multiple return values?

Goodlookinguy(Posted 2013) [#38]
Edit: I started a thread for my version

I'm not entirely sure about adding that in since that kind of code feels very strange to me. If I do though, I won't be able to merge since I altered all of the original MiniC code to use the same spacing (very inconsistent before). If on the other hand someone forks my version then adds it in and makes a pull request, I'd be willing to merge that.

Edit: You know, I was just thinking. But I'd hold off before anyone tries what I just mentioned above. I'm actually rewriting the parser to work in the correct order. The parsing as it stands is all out of whack with every other language that exists. So I got an EBNF for the C language and am basing the parser rewrite partially on that.

Like right now this...
a = b + c > 3
solves for
c > 3
then proceeds to add it. Making it look something like
a = b + (c > 3)
when it should actually be (esp. if this is based on C)
a = (b + c) > 3

Edit 2: The changes I'm making to the parser are fairly huge. MiniC will still be fairly small, but it will now support basic things that were skipped. Like scientific notation, hexadecimal, and binary. As well as all major operators with the exception of pointers and things like that. I'm also adding in primary datatype casting because I need it and I figure so will everyone else. It'll come in the form of "(expr) as (type)".