-
-
Notifications
You must be signed in to change notification settings - Fork 5
Language Features
Note
Assume we are starting from Javascript/Python, which is the closest to adhoc.
Every dereferenced value is a nil
, instead of a null
.
Modules have a completely different meaning in Adhoc. Think of them as C++ namespaces, they can be navigated to.
Classes also exist, but are only used to define types that inherit from the base Adhoc objects.
Either of them supports functions and methods.
module MyModule
{
function myFunction() { ... }
method myMethod() { ... } // Note the keyword 'method'
}
For statics, the keyword static
is used. They are accessed in a C++ namespace manner, or through []
indexing:
module StaticModule
{
static PI = 3.14;
}
// Access static field
var pi = StaticModule::PI;
// Access a static field by name
var pi = StaticModule["PI"];
// Navigating through engine modules to call a function
pdistd::MPjson::Encode(/* ... */);
If you need to use something from the global modules/top-level and ignore current module scope, you can use the ::
operator prefix (similar to C++'s scope resolution operator):
static x = 1;
function test_func()
{
var x = 2;
print ::x; // would print 1
}
Properties are called attributes in adhoc. They are defined with the attribute
keyword, just like how you would declare a var
or static
.
- Without value:
attribute myAttribute
- Will be defaulted tonil
- With value:
attribute myAttribute = []
class Dog
{
attribute name;
}
Attributes can also be defined in modules.
Class constructors are defined with the __init__
method identifier.
Local attributes are accessed using the self
keyword.
class Dog
{
attribute name;
method __init__(name)
{
self.name = name;
}
}
var obj = MyObject("FooBar");
To access an attribute:
var name = obj.name;
The :
token instead of extends
in Javascript or Java.
class BetterObject
{
...
}
class EvenBetterObject : BetterObject
{
...
}
Module constructors are completely new in Adhoc. These are mostly used for initializing UI widgets with user data or with UI method events.
They allow defining a constructor for any object that will run once the UI system sees a new object registered (i.e appendChild
onto a composite)
var myObject = someWidget.doCopy();
module (myObject)
{
attribute myAttr;
method onCancel()
{
// ...
}
}
myObject.myAttr; // ❌ myAttr is not yet defined!
There is only one type of string declaration, quotes.
var str = "Hello world!";
var combinedStrings = "hello"
"world!";
var interpolated = "hello, %{name}!"; // Notice %, instead of $ in javascript.
Maps are Key/Value collections, similar to javascript's map or C#'s dictionaries. Adhoc supports them natively.
var myMap = Map();
var myMap2 = [:]; // Shortcut to creation
var myMapWithElements = ["MyKey":"MyValue", "MyKey2": "MyValue2"]; // Creation with 2 pairs
myMap["hello"] = "world!";
myMap.getMapCount(); // 1
myMapWithElements.getMapCount(); // 2
Adhoc supports foreach
clauses out of the box.
var arr = ["one", "two", "three"];
var combined;
foreach (var i in arr)
combined += i + " ";
// combined = "one two three "
Also works with maps.
var map = ["Name": "Bob", Age": 18];
foreach (var [key, value] in map) // Pair deconstruction
{
// ...
}
Supported as C supports it
#define ADD(x,y) (x+y)
var val = ADD(5, 6)
UInt
, Long
, ULong
, Double
respectively are all natively built-in types starting from GT PSP Adhoc) ontop of Bool
, Int
, Float
.
Imports are mostly used python-like.
import main::*; // Imports/copies all modules from the specified module into the current one.
import myModule::myFunction; // Imports/copies a static/function into the current one.
import myModule::myStatic as obj; // Imports a static into an object.
C-type includes are supported.
#include "projects/gt6/my_project/myinclude.ad"
Variables outside function expressions are captured.
var myVariable = 0;
var myFunc = function (){
return myVariable + 100;
}
Top level, in module or class bodies, code is allowed everywhere.
module MyModule
{
attribute myAttribute = [];
myAttribute.push("hello world");
}
Module extensions are also allowed within function themselves.
function myFunction()
{
module main
{
// Anything put here will be part of the "main" module.
// Declaring a static variable will make it belong to the "main" module.
}
}
Undefs let you undefine functions or static symbols.
function myFunction()
{
...
}
undef myFunction; // "myFunction" is undefined, now nil if called.
Adhoc supports fully overloading operators.
class OperatorOverloadClassTest
{
attribute value = "";
method __init__(val)
{
self.value = val;
}
method __add__(val) // Needs to be the internal label for a designated operator, in this case, __add__ = +
{
return OperatorOverloadClassTest(value + val);
}
}
var obj = MyOperatorOverloadingClass();
obj += "hello world!";
// obj.value is now "hello world!"
Static fields can be accessed from any module or class depth.
module RootModule
{
static sStaticField;
module ChildModule
{
function setParentField()
{
sStaticfield = "hello world!";
}
}
}
Note
GT6 and above.
async function myAsyncFunction() // Must mark as async
{
var result = await getObject();
}
Finalizer statements allows running code once the current module is finalized/cleaned up.
function func(context)
{
CursorUtil::setCursor(context, "wait"); // Set cursor to waiting mode
finally
{
// This will be executed once the module is finalized.
// It will not execute immediately.
CursorUtil::setCursor(context, "cursor_chrome");
}
}
Mostly unknown, may be similar to unity's yield statement where the runtime waits for the next frame.
function func(context)
{
yield;
}
Requires allows importing all contents of a script onto the current one.
require "MyScript.adc"
Similar to Javascript's Symbols, they are defined with single quotes.
var symbol = 'my cool symbol';
Calling functions with their arguments being represented by an array can be called using the call()
keyword:
function sum(arg1, arg2)
{
return arg1 + arg2;
}
// call(func, argument array) - NOTE: function or method must be script defined.
call(sum, [9, 10]); // 21
Identical to javascript except the syntax is swapped around.
function myFunction(args...) // Not ...args!
{
...
}
Identifier literals allow defining identifiers with normally illegal characters incase you have to.
var `my totally valid identifier` = "hello world";
module `my module`
{
}
Note
GT Sport and above.
function myFunc()
{
return "hello world";
}
delegate myDelegate; // It is not possible to directly assign a function to a delegate
myDelegate = myFunc; // This will not override myDelegate with a function, rather assign a function to the delegate
return myDelegate(); // "hello world"
function getXY(x_ref, y_ref) // Common practice is to add the `_ref` suffix OR (less common) `ref_` prefix.
{
*x_ref = 1;
*y_ref = 1;
}
var x, y;
getXY(&x, &y);
// x = 1, y = 1
Note that you can also pass attributes/statics i.e &myobject.myattr
or even array elements i.e &MyArray[0]
.
Warning
This one is still sort of unclear.
This feature seems to allow calling grabbing method/attribute references using the .*
operator.
scripts/gt5/UsedCarList.ad
method __get_elem__(i)
{
return *(self.*attr_map[i]);
}
method __set_elem__(i, val)
{
self.*attr_map[i] = val;
}
projects/gt5/arcade/CarRoot.ad
var delay_load_complete = method(context)
{
self.Info::FadeEffect.start();
}
self.Info::tuner_logo.on_delay_load_complete = *self.*delay_load_complete;
- Anything modern ECMAScript-ish features (arguably not needed).
-
let
,const
keywords are not implemented. -
for..in
andfor..of
are replaced by the much more convenientforeach
. -
===
,!==
operators - Dynamic objects
var obj = {}
That have yet to be figured.