Forum Replies Created
-
AuthorPosts
-
After of revisiting this idea, I noticed that this actually leads to functional programming concept such as LINQ etc. From what I guess Monkey 2 will feature LINQ in the future, so I won’t plan to do a re-implementation of that. However only as an evolution of the first example, this is more of a prototype for exploring the concept further. This time I took it a step further to use Extension methods to the List class rather than writing “service classes”, this way the API becomes fluent and natural. Perhaps in the future if I get any further ideas with this it will justify the creation of a library.
The most possible future plan in mind, is to port some little game examples (perhaps some bananas) to this style of programming and see in real terms what are the benefits.
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148' listextensions.monkey2Namespace std.collections#Import "<std>"Using std.collectionsClass List<T> Extension' Foreach Extention Methods' --------------------------------------------------Method ForEach(callbackFunction:Void(element:T))For Local item := Eachin SelfcallbackFunction(item)EndEndMethod ForEachIf(callbackFunction:Void(element:T), booleanFunction:Bool(element:T))For Local item := Eachin SelfIf booleanFunction(item) Then callbackFunction(item)EndEnd' --------------------------------------------------' Filter Extention Methods' --------------------------------------------------Method Filter:List<T>(booleanFunction:Bool(element:T))Local items := New List<T>For Local item := Eachin SelfIf booleanFunction(item)items.Add(item)EndEndReturn itemsEnd' --------------------------------------------------' Find Extention Methods' --------------------------------------------------Method Find:T(booleanFunction:Bool(element:T))For Local item := Eachin SelfIf booleanFunction(item) Then Return itemEndReturn NullEnd' --------------------------------------------------' Generate Extention Methods' --------------------------------------------------Method Generate:List<T>(element:T, times:Int)Local items := New List<T>For Local count := 0 Until timesitems.Add(element)EndReturn itemsEndMethod Generate:List<T>(callbackFunction:T(), times:Int)Local items := New List<T>For Local count := 0 Until timesitems.Add(callbackFunction())EndReturn itemsEnd' --------------------------------------------------' Conversion Extention Methods' --------------------------------------------------Method Convert<U>:List<U>()Local items := New List<U>For Local item := Eachin SelfLocal converted := Cast<U>(item)If converted <> Null Then items.Add(converted)NextReturn itemsEndMethod Convert<U>:List<U>(conversionFunction:U(element:T))Local items := New List<U>For Local item := Eachin SelfLocal converted := conversionFunction(item)If converted <> Null Then items.Add(converted)NextReturn itemsEnd' --------------------------------------------------' Apply Extention Methods' --------------------------------------------------Method Apply:List<T>(element:T)Local iterator := Self.All()While Not iterator.AtEnditerator.Current = elementiterator.Bump()WendReturn SelfEndMethod Apply:List<T>(callbackFunction:T())Local iterator := Self.All()While Not iterator.AtEnditerator.Current = callbackFunction()iterator.Bump()WendReturn SelfEndMethod Apply:List<T>(callbackFunction:T(element:T))Local iterator := Self.All()While Not iterator.AtEnditerator.Current = callbackFunction(iterator.Current)iterator.Bump()WendReturn SelfEnd' --------------------------------------------------' Copy Extention Methods' --------------------------------------------------Method Copy:List<T>()Local items := New List<T>For Local item := Eachin Selfitems.Add(item)EndReturn itemsEndEndMonkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183' listextensionstests.monkey2#Import "<std>"#Import "listextensions.monkey2"Using std..Function Main()' TestExtension_Generate()' TestExtension_Foreach()' TestExtension_Filter()' TestExtension_Apply()' TestExtension_Copy()' TestExtension_Convert()End' FUNCTIONS TO TEST LIST EXTENSION METHODSFunction TestExtension_Generate()Print("Generate Extension Methods")Local data := New List<Int>().Generate(FunctionRandomInt, 10)Print("Created " + data.Count() + " numbers.")data.ForEach(FunctionPrint)Print("")EndFunction TestExtension_Foreach()Print("Foreach Extension Methods")Local data := New List<Int>().Generate(FunctionRandomInt, 10)' apply function for each element of the listPrint("print original numbers")data.ForEach(FunctionPrint)Print("")' apply function for only specific elements of the list' depending on the boolean result of the functionPrint("print numbers that are less than 50")data.ForEachIf(FunctionPrint, FunctionLessFifty)Print("")EndFunction TestExtension_Filter()Print("Filter Extension Methods")Local data := New List<Int>().Generate(FunctionRandomInt, 10)Print("print original numbers")data.ForEach(FunctionPrint)Print("")' apply a function filter the elements of the list, after that' do a chain call to apply the print function to each elementPrint("print even numbers")data.Filter(FunctionEven).ForEach(FunctionPrint)Print("")EndFunction TestExtension_Copy()Print("Copy Extension Methods")' create the first random listLocal data1 := New List<Int>().Generate(FunctionRandomInt, 10)' make a copy of the first listLocal data2 := data1.Copy()'doing a simple assignment like this -> Local data2 := data1' will result to having two lists pointing at the same object references' both will have the same data' data2 list will be mutateddata2.Apply(FunctionRandomInt)' now print the resultsPrint("values from list 1")data1.ForEach(FunctionPrint)Print("")Print("values from list 2")data2.ForEach(FunctionPrint)Print("")Print("")EndFunction TestExtension_Convert()Print("Convert Extension Methods")Local data := New List<Int>().Generate(FunctionRandomInt, 10)Print("print original numbers")data.ForEach(FunctionPrint)Print("")' convert the list to a list of another type' this will use the default behaviour of the Cast<T> commandPrint("convert to float automatically")data.Convert<Float>().ForEach(FunctionPrintGeneric<Float>)' convert the list values based on a custom functionPrint("convert to float with a function")data.Convert<Float>(FunctionIntToFloatRandom).ForEach(FunctionPrintGeneric<Float>)Print("")EndFunction TestExtension_Apply()Print("Apply Extension Methods")Local data := New List<Int>().Generate(FunctionRandomInt, 10)Print("print original numbers")data.ForEach(FunctionPrint)Print("")Print("apply a new value to each element of the list")data.Apply(Rnd(10))data.ForEach(FunctionPrint)Print("")' apply a new value to each element based on the output of a functionPrint("apply a random value by replacement")data.Apply(FunctionRandomInt)data.ForEach(FunctionPrint)Print("")' apply a new value to each element by mutating the existing valuePrint("add 100 to the existing numbers")data.Apply(FunctionAdd100)data.ForEach(FunctionPrint)Print("")Print("repeat test once again with only one chained call")data.Apply(FunctionRandomInt).Apply(FunctionAdd100).ForEach(FunctionPrint)Print("")End' OTHER HELPER FUNCTIONSFunction FunctionPrint(number:Int)Print("~t" + number)EndFunction FunctionPrintGeneric<T>(value:T)Print("~t"+value)EndFunction FunctionPrintString(string_:String)Print("~t" + string_)EndFunction FunctionRandomInt:Int()Return Cast<Int>(Rnd(1, 100))EndFunction FunctionIntToFloatRandom:Float(x:Int)Return x + Cast<Float>(Rnd(0.001, 0.1))EndFunction FunctionLessFifty:Bool(number:Int)Return number < 50EndFunction FunctionEven:Bool(number:Int)Return (number Mod 2) = 0EndFunction FunctionAdd100:Int(number:Int)Return number + 100EndFunction FunctionConvertIntToString:String(number:Int)Return "String: " + numberEndNicely done!
Great!
I want to write an interpreter too for educational purposes.
I have put on some study in it a few weeks now (first time ever) and I have completed the required knowledge about the tokenizer and the semantic model. The most tricky part is how to convert the token list to the semantic model… All of the implementations available use recursive function calls, which I dislike. Otherwise I will fall back to the most classic approach, peeking and checking…
A renderer API wrapper has to be made in this case, so the implementation is more flexible. This approach was done in Microsoft XNA because at that moment in time, they wanted to support both XBOX and Windows DX9.
I have also studied a little about the source code of BGFX, it follows the same approach of API virtualization, meaning that you can create vertex buffers and stuff, and getting the low level feeling. But you don’t care whether actually the implementation behind the scenes is OpenGL or DirectX, rather than only you care about the deployment platform.
Looks like an interesting concept, have you written an interpreter for this?
So this basically tells that if you write a special parser that understands specific source patterns, or comment tags, you would generate custom vertex attributes dynamically.
Yes, the reason is that the boolean condition that would allow the fix happen, is valid only for repeat events. Specifically is the way that modifier keys are processed.
Monkey12345678910textview.monkey2 - line 1201Method OnContentMouseEvent( event:MouseEvent ) OverrideSelect event.TypeCase EventType.MouseDownSelect event.ClicksCase 1_cursor=CharAtPoint( event.Location )' This one...If Not (event.Modifiers & Modifier.Shift) _anchor=_cursorAfter examining these *.monkey2 files in order to understand the inner workings: view, window, app, textview. The best fix for this problem, is this one.
Monkey123456789' Previous Implementation' If Not (event.Modifiers & Modifier.Shift) _anchor=_cursor' New OneIf Keyboard.KeyDown(Key.LeftShift) Or Keyboard.KeyDown(Key.RightShift)' nothingElse_anchor=_cursorEndUnfortunately I have to bypass the event mechanism and do a dirty hack (ignore the event checks) and rely on the Keyboard class. I am not proud of the solution, but it will work for now, until I find something else better better.
P.S. Some notes on this subject _________________________________________________
Regarding the proper “textview solution” would be fixed like this: app.monkey2 line 720
Monkey12345If kevent->repeat_SendKeyEvent( EventType.KeyRepeat )ElseSendKeyEvent( EventType.KeyDown )EndifEither by creating a new important event KeyPress (which captures both states of Down and Repeat) or the significance of Key.Repeat would be changed (changing it’s bitwise value) if it makes any sense to do so:
Monkey1If kevent->repeat_ SendKeyEvent( EventType.Down & EventType.KeyRepeat )I don’t know if these proposals are good or not but I though it a good opportunity to throw the ideas, and see what happens.
I would definitely be sure that 3MB is a reasonable size and that the TinyXML is solid.
Just out of curiosity if you parse the XML file with another programming language what will happen?
https://www.tutorialspoint.com/python/python_xml_processing.htmP.S. I don’t know also if there is an encoding issue as well, is the file UTF8?
Monkey1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798' ---------------------------------------------- '' IMPLEMENTATION' ---------------------------------------------- 'Interface IComponentProperty Name:StringProperty Owner:GameObject()Method OnLoad()Method OnUpdate()Method OnStop()EndClass GameObjectField List<String> Tags;Field List<IComponent> Components;Method FindComponent:IComponent(name:String)' foreach component return if name matchesEndMethod Start()EndMethod Update()EndMethod End()EndEnd' ---------------------------------------------- '' ---------------------------------------------- '' CUSTOM COMPONENTS' ---------------------------------------------- 'Class CharacterController Implements IComponent'...'EndClass EnemyAI Implements IComponent'...'End' ---------------------------------------------- '' ---------------------------------------------- '' EXAMPLE' ---------------------------------------------- '' both game objects have the same classLocal player := New GameObjectLocal enemy := New GameObject' each game object however has different behaviourplayer.Components.AddLast(New CharacterController)enemy.Components.AddLast(New EnemyAI)' ---------------------------------------------- '' OTHER NOTES' Creating an object pool is important because' you might need to fetch them at any time.Class GameObjectPool AbstractGlobal GameObjects:List<GameObject>Function Add(g:GameObject)'...EndEnd' and then at the game object constructorClass GameObject'...'Method New()GameObjectPool.Add(Self)End'...'End' Later on...' You can use global search functions.Function FindGameObjectByTag:GameObject(tag:string)'...EndFunction FindGameObjectsByTag:List<GameObject>(tag:string)'...End' Another alternative is to put them in a registry class' no need for searching the most important objects constantly.Class GameObjectRegistry AbstractGlobal Player:GameObjectGlobal Enemies:List<GameObject>EndCode is from muscle memory, unfortunately is not a perfect design, as design flaws occur they will have to be solved on the spot.
For example, just now I added “Name” + “Owner” on the IComponent.
The reason is that for example acquiring a nitro boost component, will increase the speed of movement component. This means that the “nitro compo” will send message to the “movement compo”.Monkey123456789Class NitroComponent Implements IComponentField Move:MoveComponentMethod OnLoad()Self.Move = Owner.FindComponent("Move")' Perhaps reflection also might be a good idea.EndEndVery nice! Not to mention that I am a huge fan of ODE.
Nice one.
This looks good.
Good one.
From what I see it’s called an “If Expression”
-
AuthorPosts