🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Tangent: Milestone 1 and mechanics.

Published May 17, 2008
Advertisement
I see milestone 1 on the horizon. Tangent now compiles raw source into code-dom-ish sort of structures which can be run. Type declarations are still hardcoded, and method groups have a bug where they don't get default initialized. Once that bug is fixed and I see code work I'll hit milestone one. Another 30 minutes of work or so, but I'm tired and feel like talking (to nobody as far as I can tell really).

[edit - 6 hours later]: Okay... 30 minute estimate; bad idea. Still not working due to some minor catastrophes with method groups and blocks.
[/edit]

But I'd like to take a few paragraphs and talk about some of the mechanics of Tangent which make it different (for better or worse).


The most immediate difference between Tangent and popular languages is its type system. Tangent types are statically declared like C#, Java and their kin, but do not follow a hierarchical inheritance structure (by default). A Tangent type is considered a sub-type of another if it supplies at least the required interface. Thus it provides a kind of static duck typing. Inheritance itself is provided via Mixin style type composition. Methods, Method Groups, and even Operators are all proper objects and can be passed around as such.

The second major difference is how code is parsed. Tangent follows the standard lex->parse->syntax analysis pattern for modern compiled languages, but defers all 'block' parsing to the syntax analysis step. It puts off dealing with the actual executable bits of code until the type declarations are dealt with. This is to allow custom operators.

Tangent allows operator declarations that are standard identifier names. In 'Ogre kills Player', kills would be defined as a method taking the suitable types. A Tangent statement is thus a series of identifiers (and a few other things such as member access tokens, standard +-*/... operators, parens) which results in void. Yes, that means just 2+2; as your statement yields a compile time error; sorry. The block parsing step then takes the flattened stream of identifiers and uses the type info to construct a more traditional abstract syntax tree.

The idea being that having custom operators will allow a lot more readable and thus maintainable code. Coupled with the duck typing it should also provide a better mechanism for coupling data with the operations valid upon it. An operator can require data match a particular interface without explicitly inheriting from a base type (and as such be able to work on classes in a different API with fewer adapters).


Though I am not sure how these things will quite work in practice. I think that being able to natively use .NET objects/classes will be a boon. I think that the functional capability to pass around and return methods/method groups/operators will be a boon to using functional programming style for algorithms and the sort where that really shines. I think that the type system provides many of the compile time check and explicit definition benefits that static typing offers while also allowing more flexibility where it's useful (interfaces and type composition).

Though I can also foresee some realistic cases where compile times are too long, or execution performance too poor, or statement ambiguity too common/annoying, or operation conflicts too common/annoying or the operations simply too vague about what the actual code is doing. We'll see in 3-4 more milestones when I get this puppy to the point where I can get some unbiased 3rd parties writing code in it.
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement