Menu

learining gCode

Cyder

Learning gCode

NOTE: ndy means not done, yet

1. Statements

Single statements allways end with a ";".
Statements may contain more statements. These statements are treated differently.
They are either composed from a single statement or are encased in a block-statement.

1.1. block-statement

Block statements are collections of normal statements that begin with "begin" or "{" and end with "end" or "}"
Within this tutorial I will only use "begin" and "end". But you can allways allso use the alternative.

1.2. difference statement/inline-statement

gCode is internally seperated to 4 types of code:
* Statements
* inline-statements
* value setters
* value getters
Rules:
* inline allways referrs to a value getter.
* Statements use value getters and setters and other statements
* value getters use inline statements
* inline statements use value getters and statements

2. Commenting

gCode offers multiple ways to insert comments into your code:

// this is a line comment! it ends once this line ends
/begin/

this is a multiline comment! it last until it is ended manually

/end/

NOTE: there are multiple synonyms for /begin/ and /end/:
/* ... */ (* ... *) /{/ ... /}/

3. Vars

Everything in gCode is a var (except not loaded modules)
there a 6 ways to assign a var (don't worry knowing 1 is enough)

3.1. Var Assigning

These assignment methods are considered a statement.
They cannot be performed inline

a = 1;
b := 2;
c <- 3;
d <-- 4;
5 -> e;
6 --> f;

3.1.1. modifying var assignment

a = 21;
// NOTE: the following actions can be performed inline (they returm the new value of the var being modified)
a += 19; // a is now 40
a -= 20; // a is now 20
a *= 4; // a is now 80
a /= 3; // a is now 26 (this value was truncated because a is not a floating point number)
a ^= 2; // a is now 164

3.2. Assigning Strings

Strings are allways toggled on and off by using "'". In order to write a "'" you just write "''". In order to add special characters, you end the string, write \ and either 'n','r','t' or the hexadecimal code of the char in the current context (Unicode/Ansi).
NOTE: Strings are multi-line structures
Example:

a = 'foobar'; // easy
b = 'foo'\r\n'bar'; // new line inbetween (method 1)
c = 'foo
bar'; // a real new line between (within the code -- method 2)
d = 'Hello, I''m foo.'; // string containing a '
e = \t'hello'; // string starting with a tab
f = 'hello'\t; // string ending with a tab

Please note that when using print to output a string directly, gCode will not try to recreate the sytax (probably) used to write the string, which it will do if the string is nested in a tuple or somthing else!

3.3. Del statement

Deleting vars is simple (the print statement is covered in the next chapter):

a = 5;
print a; // print 5 (expected)
del a; // deletes a
print a; // var not found exception here (for exception: see below)

You can allso delete multiple vars at once:

a,b = 1,5;
del a,b;
print a,b; // the same exception

4. Print statement

Anything in gCode can be displayed as a [String].
Because of that and the fact gCode is only designed as a console application,
print is the default interface, to give out text to the console:

print a,b,c,d,e,f;

5. Tuples

Anything in gCode can be merged into a single value. This is how a [Method] is able to return multiple values.
Tuples are created more often than you might think:
whenever you have multiple values seperated by ',' (see print statement -- 4.), you are creating a tuple internally.
Tuples work both ways: you can merge values into 1 by having too many inputs and you can expand them by having too many outputs:

a = 1,2; // too many inputs
print a; // this will display as '(1,2)'
b,c = a; // too many outputs
print b; // this will display as '1'
print c; // this will display as '2'

5.1. Stacked/Forced Tuples

Sometimes it isn't possible to create a tuple even if you need one:
You want a tuple containing another tuple.
This is done by forcing gCode to create a tuple by saying:

a = (1,2),3;
print a; // this will display as '((true 2) 3)'
Using brackets you can force gCode to create tuples
CAUTION: this only works for 2 or more values (for single values this behaves like the normal mathematical brackets):
a = (1),2;
print a; // this will display as '(1 2)'
Allso be aware of the fact, that because of that same rule:
a = 1,2,3; // this does the same
a = (1,2,3); // as this
NOTE: Creating tuples that only contain 1 value is possible though never really needed:
a = Tuple().setLen(1);
a[0] = 21; // this caused a crash in v02 (fixed in v03)
print a; // prints (21)
// working version for v02 and up
function toTuple([a]) return a;
a = toTuple(1);
print a;

6. Arrays (ndy)

Array behave and are created much like tuples. The differences being:
* arrays use '[' and ']' in for their creation.
* arrays cannot be split open by having to many outputs
* arrays don't have a limitation on holding at least 1 item

7. Operators

gCode has a lot more default operators that other languages:

print 2+3; // add
print 2-3; // subtract
print 2*3; // multiply
print 2/3; // divide
print 2^3; // power
print 2:3; // range (see below)
print 2=3; // compare: equal
print 2!=3; // compare: not equal
print 2>=3; // compare: greater,equal
print 2!>=3; // compare: not greater,equal
print 2<=3; // compare: lower,equal
print 2!<=3; // compare: not lower,equal
print 2<>3; // compare: lower,greater
print 2!<>3; // compare: not lower,greater
print 2<=>3; // compare: lower,equal,greater
print 2!<=>3; // compare: not lower,equal,greater
print a++; // increase a by 1 and print it
print a--; // decrease a by 1 and print it
print 0x0F or 0xF0; // binary/logical or (0xFF)
print 0x0F nor 0xF0; // binary/logical or (0x00)
print 0x0F and 0xF0; // binary/logical and (0x00)
print 0x0F nand 0xF0; // binary/logical and (0xFF)
print 0x0F xor 0xF0; // binary/logical xor (0xFF)
print 0x0F nxor 0xF0; // binary/logical xor (0x00)
print 0x0F shl 4; // binary shift left (0xF0)
print 0x0F nshl 4; // inverted binary shift left (0x0F)
print 0xF0 shr 4; // binary shift left (0x0F)
print 0xF0 nshr 4; // inverted binary shift left (0xF0)
print -11; // prefix: range symbol (-11)
print not 11; // prefix: binary invertion (244)
print @a; // pointer to a
print a^; // a being a pointer; src of a
Note about comparint values:
Every line in the upcomming code does the same!
print 1>=2;
print 1=>2;
print 1>>>====2;
print 1===>===2;
print 1=>=>=>>>2;
You see where I'm going with this...

8. Standard Types

Allright. Lets get this of the table.
This might sound a little bit complex for it being here so soon.
But is you don't understand it (yet), skip this part and come back here for reference.
So here are the standard types:

Typename Size Prefix Pastfix Range Description Can be condition
[UInt1] 1 u1 0:1 allso known as boolean yes
[UInt8] 1 u8,b 0:255 allso known as byte yes
[UInt16] 2 u16,w 0:65535 allso known as word yes
[UInt32] 4 u32,lw,
!new in v02!: c
0:4294967295 allso known as longword yes
[UInt64] 8 u64 0:18446744073709551615 yes
[SInt8] 1 s8,sh -128:127 allso known as shortInt yes
[SInt16] 2 s16,sm -32768:32767 allso known as smallInt yes
[SInt32] 4 s32,i,li -2147483648:2147483647 allso known as longInt/Integer/Int yes
[SInt64] 8 s64 -9223372036854775808:9223372036854775807 yes
[Pointer] 4 0x00000000:0xFFFFFFFF no
[Float] 4 f ... yes
[Real48] 6 r48 ... yes
[Currency] 8 c ... yes
[Double] 4 d ... yes
[Extended] 4 e ... yes
[UnicodeString] 8 u a string made up out of unicode characters no
[AnsiString] ndy a ndy ndy ndy
[WideString] ndy w ndy ndy ndy
[ShortString] ndy s ndy ndy ndy
[Char] ndy c ndy ndy ndy
[AnsiChar] ndy ac ndy ndy ndy
[Tuple] 8 ( ) contains gC-vars no
[Array] ndy [ ] ndy ndy ndy

NOTE: When not using a prefix/pasfix, gCode will allways choose the smallest possible type for data storage

9. If-Statement

The if statement is the most basic way to create conditional code:

if condition

then print 'condition is true'
else print 'condition is false';

// remember the rules about statement blocks for multi-statement sub-blocks:
if condition then begin

print 'condition is true'; // note how I have to set ';' here
print 'allso this is a 2nd statement in the true-block';

end else begin

print 'condition is false'; // ^
print 'allso this is a 2nd statement in the false-block';

end;
HINT: you can allso stack multiple if-statements onto each other:
if condition1 then print 1 else
if condition2 then print 2 else
if condition3 then print 3 else
if condition4 then print 4 else
if condition5 then print 5 else
if condition6 then print 6 else
if condition7 then print 7 else

print 'conditions 1:7 are all false';

NOTE: To see all standart types that can be conditions: see 6.

9.1. Inline If-Statement

The If statement is one of the lucky statements that can be used inline

print if condition then 'That is correct' else 'Sorry, thats wrong'; // response to an anser?
print base+(if addvar1 then var1 else 0); // add var1 to base if addvar1 is true

10. Seqences

Now we allready know 1 sequence type: Tuple.
But a lot of things can be sequenced (even (un)signed numbers) what these sequences do and how they behave it different for each of them.
To work with sequences, you have 5 different operations:

a = 1,2,3;
print #a,len#a; // length of a sequence (3)
print lo#a,low#a; // lowest valid index of a sequence (0)
print hi#a,high#a; // highest valid index of a sequence (2)
print 2 in a; // is a given object in the sequence? (true)
print a[0]; // item as position 0
print a[n]; // item as position n
// NOTE: if your not into binary: skip this part
a = 0x0F;
print a[0]; // get the 0 bit
a[0] = true; // set the 0 bit

11. Conditional Loops

gCode has 2 basic conditional loops:
The while loop:

a = 0;
while a<20 do print 'foo'+(a++);
a = 0;
while a<20 do begin

print a+'. loop';
a++;

end;
The repeat loop:
a = 0;
repeat print a++ until a>20;
a = 0;
repeat begin

print 'loop!';
print 'Iteraction',a++;

end until a>20;

12. Non-Conditional Loops (for)

gCode has 2 non-conditional loop:
the for .. to .. do

for i = 10 to 20 do print i; // prints the numbers 10 to 20
// remember the rules about var assignment -- you don't have to write '='. you can do :=, <-, etc.
for i = 20 to 10 do print i; // prints the numbers 20 to 10 (counting down)
the for .. in .. do
for i in 'foobar' do print i;
Note for .. in .. do uses the seqence mechanics internally

12.1. inline for

the for .. in .. do statement can allso be used inline.
When used it creates a new tuples composed of all entry of the object it was working with.
This statement is very handy if you want to manipulate some for of sequence and store the manipulated version in a tuple

a = 'foobar';
b = ('_'+c+'_') for c in a;
print b; // b is a tuple composed out of 6 strings: ('_f_','_o_',...)

13. Calling methods

For all this time up to now you've been using print to display everything.
But did you know that print is just a method (that you could even overwrite and replace with your own method)?
Of course you did. But the way you call print is not the standard way to call a method. print is only there, to make things easier.
By default you call something by writing *object*([*params*]).

print type(21); // this will print UInt8
// ^ type is a default method that return the type-var of every value it is called with
// ^ its return value is passed on to the print method with converts the value to a string
// ^ and outputs it to the console

14. Methods (function Statement)

gCode has uses 2 different method types internally:
* return method
* resultVar method
Example for a return method:

function foo() return 21;
// function foo() begin return 21; end; // remember, that this does the same thing
print foo(); // call my function foo and print its return value (21)

NOTE: return is a statement that behaves and can be used just like print
NOTE2: it allso exits out of the methpd
Example for a result-var method:

function bar(): result begin

result = 21;
print result; // prints 21

end;
a = bar();
print a++; // prints 22

NOTE: result is just the name of the return var. You could name it anything. The important thing to keep in mind is the ':' after the ()
NOTE2: gCode has some [standart methods], that will allways be loaded when you start it.

14.1. Parameters/varArgs

Now you might be wondering how do I create a method that can not only return but allso get values.
Well... heres how you do it:

function sum(a,b,c) return a+b+c;
print sum(1,2,3); // prints 6

Ok. but you talked about methods accepting a vaiable amount of parameters.
Well... heres how you do that:

function sum([params]): result begin

result = 0i; // create result as an integer value
for value in params do

result += value;

end;
print sum(1,2); // prints 3
print sum(3,4,5); // prints 12
print sum(6,7,8,9); // prints 30

14.2. Inline methods

You can allso define methods inline by just leaving out the name:

foo,bar =

function() begin print 'foo'; return 1; end,
function(): result begin print 'bar'; result = 2; end;

print foo(); // prints 'foo' and 1
print bar(); // prints 'bar' and 2

15. Attributes

Anything in gCode can have attributes. Oftenly attributes are helper methods of sub-components.
Attributes are accessed by writing object.attributeName.
HINT: For a list of all attributes of a var, visit the types page in this wiki.

a = 21i; // integer -- 21
print a.asHex(); // asHex returns a string composed out of the hexadecimal representation of a

16. Number systems

If you don't like binary, you can skip this part!
gCode supports 5 number systems for In and Output by default
* Binary
* Quad
* Octal
* Decimal
* Hexadecimal

For input you can write:

a = 0b01; // binary
a = 0q0123; // quad
a = 0o01234567; // octal
a = 1234567890; // decimal
a = 0x0123456789ABCDEF; // hexadecimal

For output you can write:

print a.asBin(); // binary
print a.asQuad(); // quad
print a.asOct(); // octal
print a; // decimal (obviously)
print a.asHex(); // hexadecimal

NOTE: even when entered in a custom number system, you can still use pre/pastfixes and gCode will still try to compile the value into smallest available type

17. Slice

A Slice is composed out of 2 vars (left and right).
Systax (allready mentioned above): *left*:*right*
Slice ange useage example:

for i in 1:100 do print i; // prints all values between 1 and 100 (inclusive)
a = 1:100;
s = 1:100;
for I = 0 to 101 do

print str(I).iZFill(4).iLJust(8),I in s;

// ^ check for each value bewteen
// 0:101, if it is within 1:100
print s.left;
// ^ left bound of the slice
print s.right;
// ^ right bound of the slice
r = s.range(); // tuple of all values s represents
for line in r.spread(10) do

print (str(a).iZFill(3)) for a in line;

NOTE: Slices do not cache all the values inbetween. Those are calculated as you request them
NOTE2: In the future Slices will be a to retrieve multiple values from a seqence

18. Default Methods

Whenever an instance of gCode is started, you will start out with a bunch of default methods. These methods don't have to be imported manually but are included by default.
Though you can overwrite and modify them, that is not recommended, because it may break your code.
For a list and description of all default fields see here [standart methods].

19. Modules

To seperate merge and dynamically use code, gCode comes equipped with a Modules System.
A modules is considered to be a single file located in any on the lib folders (see [libs.ini]).
Modules and parts of modules can be imported at any time using the include statement.

19.1. Include Statement

include math; // this includes the math modules. After this it is accessible by typing math.*field*
include pi from math; // this only include the field pi from math. After this is is accessible as pi
include pi from math as myPi; // does the same but pi is now accessible as myPi
include * from math; // includes every field from math. these fields are accessible by typing their original name

For more info on what the * does, visit [formatted string match].
Usage example:

include random from math as rand;
print rand(); // print a random extended in the range 0:1

20. Pointers

I won't go over what a Pointer is in here. What I will go over is:
* Binary, custom data interpretation
* Creating a pointer
* Getting the source of a pointer
* Creating custom data structures
* Helper methods
* Risks

20.1. Binary, custom data interpretation

You can Interpret anything in gCode in any way on a binary level by calling the type you wan't to
interpret an object as with the object as parameter.

a = -100;
print UInt8(a); // this will interpret the data allocated by a as a UInt8 (prints 156)

Hint: if you want to convert a value to a different type, goto the types page and look through its attributes

20.2. Creating a pointer

Pointers are created by using the '@' operator (see operators above)

b = @a; // b is now a pointer to a

20.3. Getting the source of a pointer

Pointer sources are accessed by the '^' operator (see operators aboce)

c = b^; // c is not an untyped piece of data located at the source of b

NOTE: this is where 18.1. custom data interpretation comes in

a = 21; // a var
b = @a; // a pointer to the var
c = type(a)(b^); // c is a fully typed var (of the same type as a) with the same data address as a
// NOTE: c does know, that it does not own the data it points to, and thereby will not try to do so

20.4. Creating custom data structures

Call the type you want to have a structor of without any parameters:

a = SInt8(); // a is now an empty hull for a SInt8
To design your own data structure: see [Record] and the tutorial below

20.5. Helper methods

  • addr -- [standart methods] -- addr returns the address of an object in ram.
  • !new in v02! newMem -- [standart methods] -- newMem can be used to manually allocate RAM of a custom size/pos
  • !new in v02! freeMem -- [standart methods] -- freeMem can be used to manually deallocate RAM of a custom size/pos

20.6. Risks

The gCode var-management system (see [under the hood]) is designed to automatically and instantly unload anything thats no longer used anywhere.
Pointers are very natural and are not designed, to fit in with that system.
That can lead to pointers pointing to vars that are no longer loaded.
As a generic rule: Anything, that you can't access by name is not / no longer loaded.
Though this isn't necessarily a problem, you should NEVER create global pointers pointing to local vars!
Just allways keep your pointers in a higher or the same [stack frame] than their destination.

21. Binary structures

gCode supports direct coding of binary structures. For this you can use the type [Record]. Inspired by pascal records and known as structures in C, this type can define collections of data.

21.1. Defining binary structures

myStruct = Record();
myStruct.x = SInt32; // add a field called x that is a SInt32
myStruct.y = SInt32; // ... called y ...
myStruct.lock();

NOTE: prior to v02, to add a field you would have to use this code:

// this still works, but is deprecated and may be dropped at some point
myStruct.addField('x',SInt32);

The method "lock()" should be called once the record is completely declared. It locks the record definition from being edited again. This should be done to ensure that the record won't change while instances are being used.

21.2. Using binary structures

After a structure is defined, it can be instanciated like all other types:

inst = myStruct();
// inst is a 16-bit structure build up out of 2 SInt32s
inst.x = 21i; // set the x field to 21
inst.y = 15i; // set the y field to 15
print inst; // prints a big chunk of data containing all information about the structure and instance

21.3. Advanced integration

Records can not only be used to store data. You can add methods to them:

myStruct2 = Record();
myStruct2.x = SInt32;
myStruct2.y = SInt32;
myStruct2.sum = function(self) return self.x+self.y; // sum adds x and y together
myStruct2.lock();
inst = myStruct2()
inst.x = 9i;
inst.y = 11i;
print inst.sum(); // prints 20

NOTE: prior to v02, to add a method you would have to use this code:

// this still works, but is deprecated and may be dropped at some point
myStruct2.addMethod('sum',function(self) return self.x+self.y);

!new in v02! Using this method system, you can allso overwrite internal events:

myStruct3 = Record();
myStruct3.x = SInt32;
myStruct3.y = SInt32;
myStruct3.__init__ = function(self) print 'myStruct3 instance created';
myStruct3.__del__ = function(self) print 'myStruct3 instance deleted';
myStruct3.lock();
inst = myStruct3(); // __init__ is called in this
del inst; // __del__ is called in this

Here is a list of all events, call conditions, params and expected return values

Method name call condition params expected return value desc
__init__ called when an instance is created (instance) - could be used to specify default values a record should be created with or create custom data
__del__ called when an instance is deleted (instance) - could be used to drop custom data
__getItem__ inst[loc] (instance,loc) item at loc could be used to create a pseudo array
__setItem__ inst[loc] = value (instance,loc,value) - could be used to create a pseudo array
__getSlice__ inst[loc] (instance,loc) slice from loc.left to loc.right only called, if loc is a slice (__getItem__ is called otherwise)
__setSlice__ inst[loc] = value (instance,loc,value) - only called, if loc is a slice (__setItem__ is called otherwise)
__in__ value in inst (instance,value) boolean returns if value is in inst
__hi__ hi#inst (instance) highest array index should return the highest values that can be used in __getItem__ or __setItem__
__lo__ lo#inst (instance) lowest array index should return the lowest value that can be used in __getItem__ or __setItem__
__len__ #inst (instance) amount of array indices should return the amount of values that can be used in __getItem__ or __setItem__ (usually abs(hi#inst-lo#inst)+1)

HINT: for a good example use of all the features of records, see "File" in module "fs"


Related

Wiki: Home
Wiki: libs.ini
Wiki: standart methods

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.