Tag Archives: functions

Recursive and ancestor calls — again

I‘ve just brought self and super calls back — more about these features in my previous post about them.

I am just not happy how super is implemented currently — I was forced to add initial stage of scanning all the signatures of types and functions in order to compute function derivation tables. So when I hit the body of the function — during the second stage of processing — I am able to bind super properly.

Advertisement
Tagged , ,

Inline functions

I jumped too prematurely to implementing inline functions as I would do it in a language compiled to machine code — namely just put the function instead of the call and that’s it. The problem with backends such as PHP or Javascript is you get the explosion of code which has to be processed by the backend engine, so instead of savings there would be a loss on duplicated code.

To make inline functions useful and predictable I inline them always (it is not just a hint as in C++) and such functions have draconian requirements — just single expression, parameters can be used once at most, no static data used and only standalone functions can be inlined. After reshaping assert to meet those criteria it looks as following:

inline def assert(cond ?Bool,msg String = "", 
                  details: String ... = []) Void 
  %% this code will be put instead of the call
  => assertPassed(cond) ? void : fail(msg,*details);

I did some unscientific tests and I was happy to observe there was no test running slower, in some cases I saved 25% of running time. No complains from me.

Tagged , ,

C++ const – how to make it happen?

The latest list of changes (not done yet) includes regular constructor (not returning anything), variadic syntax as in Go (“x ...Int”) and “procs” (for mutating methods) and “funcs” (not mutating, can be prefixed with “|”).

This is related to C++-like “const” ¹ — I am that guy who loves this feature (maybe not execution), however I am both a bit clueless how to implement it correctly and I am a bit afraid if I understand the concept (considering almighty MS gave up on this having so many smart people). I think there could be only two constants — constant pointer to some data (constant or not) and deep constant data (immutable view of data).

It might sounds funny but I don’t even have good names for them — say “lnk” for fixed pointer (“ptr” for regular one), but what for data? If possible I would like avoid “const” (to avoid naysayers with standard “it does not guarantee the object is constant after all”, and to keep good keyword for constants like mathematical Pi). “view”?


¹ Interesting posts at SO: Why there is no const member method in C# and const parameter?, Why const parameters are not allowed in C#? and “const correctness” in C#.

Tagged , , , , , ,

Dropping features — multi dispatch functions

The easiest part is removing missing features like multi dispatch functions. My recent discovery of Nimrod language gave me a lot to read — it is very likely I will copy the memory model of it.

However one thing for now I consider as no-go — multi dispatch methods (multi-methods). With single dispatch you can say the object owns the function, and thus owns the call (no such ownership with regular, standalone, functions, but there is no problem either, because there is no dynamic dispatch). Thanks to that the function you think should be called will be called, it is guaranteed by the object (owner).

There is no guarantee with multi dispatch — you see some call, and you cannot tell (by looking at the call) what function will be called. The only safe situation is if compiler gives you an error saying at compile time that it cannot resolve the call in any possible way — except for this you have to pay close attention what modules you imported, one less, one more, and the resolution will be altered.

In other words — call resolution is not dependent on the line with call, but on import section. The design I am not willing to see in Skila.

Another change in design is decorating mutable methods — I copied the idea from Ruby, but now I changed it a bit after pondering on pair of “get” and “!set”. It is ugly, plain and simple. Thus you decorate the immutable methods which have mutable counterparts. This gives you nice “get” and “set”, and also “reverse” and “|reverse” (the decoration character can be changed in future). Because of this now all the function results are by default required to read, there is no longer symbol to make them required because they are already. So, another simplification.

The current decoration symbol is chosen on purpose to resemble Unix shell:

  var processed = data | sort() | reverse();
Tagged , , , ,

Variadic functions — it’s clean up time

OK, I did it. The last feature I wanted to have in my intro toolbox — variadic functions. This time I borrowed the design from Scala, not from C# because I like it better — especially in cases when you use template function and it is unclear whether your array will be passed as one argument or expanded to multiple arguments:

var arr = new Array<Int>(5);
foo(arr);
foo(arr:~);

Assuming “foo” is variadic function taking “Ints” the first call is incorrect, only the second works because it unfolds entire array and passes the values one by one (technically it unfolds nothing, it is just semantic notion).

However even Scala is not complete — too often I need to write variadic function with at least 2 parameters. Since I didn’t see everything Skila has flexible limits:

func foo(params[2..20] p Int) ...
func foo(params[2..] p Int) ...
func foo(params[..20] p Int) ...
// not too much sense, if you ask me
func foo(params[2] p Int) ... 

I could say this is the time I rest a bit, rethink syntax, try to write some programs for real, and finally upload the first version of Skila (no matter how embarrassing the code looks like — it is a mess, seriously).

But as it appeared with recent issue of Dr.Dobb’s I also have to read more about programming language Nimrod. At first glance it seems it is well designed, with similar concepts in mind as Skila — I would not like to duplicate the efforts so I have to make sure it is not the last stop for Skila.

Tagged , ,

Code injects — collections are getting closer

I see a scary pattern lately. I add new feature to Skila pretty quickly, but when it comes to cleaning the code (sadly, it is messy) I can spend a day on refactoring, polishing, removing dead pieces, and at the end it appears that I cleaned away one thing too many and I have no clue how to fix it while moving forward — so instead I have to rewind the changes, I make half of them again with commit on each step, and then I am too tired to make the second half, so I call it a day (the second one). The weekend just passes and I don’t know when…

I am working on at least one collection to introduce variadic functions in Skila, and this is the time when Skila and target language have to meet in the same code:

class Array<T>
	<?php
	public $data;
	?>

	func construct(size Int) do
		@ = size;
		<?php
		$this->data = array();
		?>
	end  
end

So far I didn’t solved the name matching problem, I rely on common sense of Skila translator, but I am too eager to finally see Skila programs working.

Tagged , , , , , ,

struct/class — changing the course

After some considerations I decided to steer away from muddy waters of improving everything related to types and objects management in one take. It does not take the genius to notice it is a vast area to cover and I will have plenty of work merging C# value and reference types with C++ mutable/const attributes with non-/nullable pointers.

This is already the challenge because with such variety of features it is easy to produce some obscure syntax. So I changed my perspective — keep it simple, make one step at a time, scratch only if it itches.

struct” is value type in Skila exactly like it is in C#. There is richer annotation though:

var x Struct = new Struct();
const y Struct = new Struct();

The first line declares a variable, thus you can change the data of “x”. The second line declares a constant — this works like in C++, so it is logical immutability, not the bitwise one.

The same modifier can be applied when passing “struct” to a function:

def foo(var a Struct) ...
def bar(const b Struct) ...

By default the parameter data is assumed to be constant so you can drop “const” in the second line.

The first line is more interesting — it tells you can change the data and those changes will be visible on caller side. So from caller perspective it is a side effect — it should not go unnoticed and it doesn’t:

foo(!x);
bar(x);
bar(y);

Those are valid calls — just like with mutating methods there is exclamation mark added as acknowledgment of alteration of “x” variable.

I didn’t add ability to pass a copy of the variable which could be changed just inside the function (pass by value). Time will tell if it is needed, now I move to C# “class” — it is a bit more problematic, because the data can be constant, the reference can be constant, and a reference can be “null” — the syntax is just boiling over.

Tagged , , , , , ,

All little Saturday things

I confess — I am a traitor. Over a week ago I enrolled in Coursera course “Discrete Optimization” by Prof. Pascal Van Hentenryck and it is frustratingly interesting if I may say that. Since I love computational challenges I was hooked in since the first assignment. I tried to keep the weekend only for Skila, but I failed — writing one thing, and thinking about other makes no sense, so I switched and worked on DO almost entire Sunday. But don’t despair, I am a thorough guy, I wrote down how many hours I borrowed from Skila.

It doesn’t mean I did nothing — however only a little additions and improvements:

  • I optimized backend in case of non-virtual types (simply no virtual table),
  • in backend layer interfaces are classes with empty methods — this allows to safely call a method when derived class hides it,
  • I added standalone functions — this required surprisingly some work,
  • I already mentioned covariance when it comes to polymorphic methods,
  • Skila supports 4 types of expressing the base for numbers like in Python — “124” for decimal, “0xCAFE” for hexadecimal, “0o57” for octal and “0b010101” for binary,
  • numbers can be expressed with padding as in Ruby — “450_010” is exactly the same as “450010” only reading is easier,

Next point is exposing back shadowed methods — I have in mind three cases:

using base::foo(Int);
using base::foo(*);
using base::foo;

The first one brings up method foo with given signature, joker “*” in the second line brings all foo methods. And third one is a shortcut — if there is only one method foo in inherited class it will be brought up. If there are more — compiler will give you an error.

And that’s all for the Saturday, I am running back to DO assignments…

Tagged , , , , , , , , , , , ,

First step into covariant world

It is interesting how given concepts of programming languages made their way into the mainstream — I was able to observe how functions from “uhm, do we really need them?” perspective became first class citizens (“what, you cannot pass a function to a function?”).

The next thing on my watch list is covariance and contravariance — they were finally introduced in C#, but sadly, only partially.

Since I am working back and forth now on improving support of functions in Skila it was a hard to miss an opportunity to finally make this happen:

struct Foo 
  def virtual get() Foo = new Foo();
end

struct Bar : Foo
  def override get() Bar = new Bar();
end

You don’t have to mark those methods in any special way, compiler knows you are overriding the method, so you can return a derived type in a derived class. That’s it — done!

Adding this/self (self reference to current type instance) and THIS/SELF (per analogy, current type) is right behind the corner. In a way it will be a return to one of the COOL features, yet with more flexibility.

Tagged , , , , , ,

Constraints on parameter value

From now on I will use term pointer both for not-null pointers and possible-null pointers. Just to avoid confusion with the mechanism I describe below.

You can declare a function parameter value with 3 types of constraints:

def foo(x MyClass)

is shorter form of:

def foo(val x MyClass)

The argument is passed by value and you have a guarantee you cannot change “x” inside “foo”. If you need speed and you know you work in single-threaded environment you could use a shortcut (both forms are shown):

def foo(ptr x MyClass)
def foo(ptr val x MyClass)

The argument is passed by pointer (fast), but since compiler guarantees the data is not changed inside a function, the only worry is whether the callee continues to work or not.

The second type:

def foo(var x MyClass)

The execution is slow (value is copied), you can change the value inside the function but the alterations do not leak outside.

And third one:

def foo(ref x MyClass)

Execution is fast and not only you can change the value inside, but any change is also visible outside the function (argument is passed via reference). However because a callee is affected you have to pass the argument consciously:

foo(ref x);

All the checking is done during compile time. However one constraint is missing — declaring a function which takes constant and forces callee it is constant as well. Too academic?

Consider creating a dictionary (a collection that maps keys on values). For fast retrieval usually a dictionary orders keys in some way — the algorithm is not important, all we know that keys are kept in some order, and dictionary uses this fact to skip a good portion of the keys when doing lookup. If you create dictionary and pass initial data, and then you change the keys on a callee side, the dictionary will not know about the change, and it won’t reorder the keys. Thus on next retrieval you can expect anything, which translates to “undefined behaviour”.
One way to solve this problem would be cloning all the keys, but this is inefficient and kills any attempt to optimize the algorithm (once you embed cloning in the dictionary you cannot get rid of it from the outside).

So far I see two ways to solve this — either add another constraint:

def foo(const x MyClass)

Meaning — I cannot change “x” inside, and I also require “x” is constant outside. In other words, the value has to be generally constant, not just in local scope. Since it is const two ways it can by passed silently via pointer (fast); note that passing the data explicitly by pointer (“ptr val”) does not give a guarantee on true constness.

Or go Ruby way and provide a method ”freeze” that would lock object against writing. I prefer the first approach (enforced during compilation) but I am not sure whether this is doable, it looks suspiciously tempting.

I like the idea of setting constraints on both sides, however even in this post I already see too rich syntax. Those constraints are much better if they are triggered automatically — for example knowing the call is done synchronously or not (for 100%) could allow automatic optimization how to pass data efficiently, by pointer or by value.

Tagged , , , ,