A guide to exploring the Transcendence codebase

Help building, determining code organization, and other new-to-project problems.
Post Reply
bzm3r
Militia Lieutenant
Militia Lieutenant
Posts: 100
Joined: Tue Oct 23, 2012 2:38 pm

George has been kind of enough to be giving me tips on how to explore the Transcendence codebase. I am going to document our conversations (in a cleaned up way), so that everyone gets to benefit. I might have made mistakes, so please let me know if you find one! Also, please feel to add your own findings or documentation, and I will merge them into the main guide -- likely, it would be better to set this up in the wiki, if someone knows how!

Why bother doing any of this?

So that together, we can build something very rare: a lasting game. From https://kronosaur.com/:
Kronosaur Productions is dedicated to creating epic-scale games on an indie budget.

Whether ruling an empire of a thousand suns or journeying to the Galactic Core with the fate of the galaxy in your hands, you will experience games that are:

Enduring: We want our games to grow and evolve over decades; we are not interested in disposable games.

Elaborate: We aim for detail, depth, and richness in all our games. We want to build living universes for you to explore and get lost in.

Extensible: We design our games to be taken apart and augmented with your own creativity. We want you to be a participant, not just a player.
Building Transcendence

The README for the Transcendence repo on github now contains (more) detailed instructions on how to build Transcendence: https://github.com/kronosaur/Transcende ... ter/README

Visual Studio Community can be downloaded free of charge from Microsoft's website. If you are not sure which Visual Studio version to get, it's useful.

Please note that the README is a prerequisite for reading this guide, if you intend to be able to understand it fully, as I am assuming you have the relevant repositories on you computer, and have built Transcendence.

Once you have Transcendence built, now what?

A bird's eye view of the tip of the iceberg

You will have downloaded three repositories, if you followed the README's instructions.

Alchemy: A set of utility and foundational functions. All are generic—they are not specific to Transcendence. One thing that may or may not be of interest is the TArray.h file, which implements a basic dynamic array object. This is an example of a “template” in C++, which allows a type-safe object that can handle an arbitrary type. That is, we can create an array of integers as easily as an array of complex objects.

Another interesting piece of this repository is probably CodeChain, which is the implementation of the TransLisp/XML compiler. CodeChain implements the basic language (keywords like “if” “while” etc.). There is also a file called CCExtensions.cpp which implements Transcendence-specific functions (like “shpOrder”). Decoding this fully is an undergraduate-level course by itself, and probably not necessary, depending on your goals. Basically, CodeChain implements a scripting language (like Python, but much less sophisticated). We build up a datastructure representing a sequence of function calls; then we step through the datastructure executing each function.

XML will get parsed into a C++ object. Basically, each top-level XML element gets loaded into a C++ object. For example, <ShipClass> gets loaded into a CShipClass object. <StationType> gets loaded into a CStationType object (other names don’t always match up, but the principle is the same). All of these objects are known as “design types” and they inherit from the CDesignType base class. Look at CDesignCollection.cpp for more.

Transcendence: Contains the heart of the Transcendence related code.

Mammoth: Transcendence is meant to be one game out of an environment of related games (for example, CSC America, or future multiplayer games). These games (probably) will be related not only in terms of the game universe, but also the basic pieces of code that they use. Mammoth contains code that is likely to be shared between games.

Landing on the tip of the iceberg

Much of the game is implemented as XML and TLisp scripts. These define the star systems, the enemies, missions, etc. Take a look at some of the stuff here.

The C++ parts implement the game engine, which load the XML and run everything. As mentioned before, the CodeChain file that parse the TLisp? The XMLUtil files handle parsing the XML.

The core animation loop is here.

30 times per second we call this function, which (conceptually) does two things: 1: paint a frame, 2: update the state of the game one tick.Most of the update happens here. This code updates all objects in a star system. It deals with collisions (missiles/beams hitting things), AI, and player controls.

The CSpaceObject class is an abstract class from which the relevant classes derive. CShip, CStation, and CMissile are all descendants of CSpaceObject. For example, in this code we loop over every object in the system (ships, station, missiles, etc.) and update them. The call to Update ends up in a different place depending on the type of object. For example, for ships, it goes here, while for stations it goes here.

The sequence of events for calling OnUpdate for an object is: CTranscendenceWnd::Animate calls Update
CSystem::Update which calls one of (CIntroShipController::Behavior, IShipController::Behavior, CBaseShipAI:Behavior, etc.) depending on the "type" of pObj (hence pObj->Behavior, since -> is the dereference operator). The Behavior functions set the "attitude" (attack or not) for "ship type" objects, but the "Update", which subsequently calls "OnUpdate". "OnUpdate" is where the AI rules are gotten, for objects that have an AI. Ships have a “Behavior” call and an “Update” call. Behavior is where most of the AI work is done. Behavior is in charge of following the ship’s orders as best as possible. The Behavior function will then set flags and variables in the object to direct the ship. For example, it might set the maneuver variable to “turn right”. The Update code is then responsible for actually turning right.

Painting (graphically displaying) is actually spread out over a couple of places. Each object knows how to paint itself, but CTranscendenceWnd paints the user interface for player (scanners, armor/shields display, etc.).

First steps on the iceberg

TransLisp code, along with XML files, are used to instruct the "Transcendence Compiler" on how to set up the game world. So, it might be interesting for to learn how TransLisp works -- whether in order to write new TransLisp functions, or understand existing functionality. Assuming you have some version of Visual Studio installed on your computer, and that you know how to open up the Transcendence solution file (explained in the README):

1) Go to TransData and set it as the StartUp project (contrast with how you set Transcendence as the StartUp Project, if/when you followed the README instructions: the start up project sets which project execution will begin from, as there are at least a couple of different "main.cpp"s: Transcendence's and TransData's).

2) Right click on TransData, and go to Properties

3) Properties -> Configuration -> Debugging -> Command Arguments: "/run"
This specifies what command line arguments should be taken by TransData when it is run, in this case, "/run"

4) Functions are defined in DefPrimitives.h. Functions are implemeted either in CCExtensions.cpp or Functions.cpp.

5) Click "Start Debugging" or hit "F5"

6) A command line should have come up (Loading...done) etc. and you should be at a command prompt (of the TLisp Shell)

Code: Select all

TLisp Shell 3.2.2
Copyright (c) 2001-2014 by Kronosaur Productions, LLC. All Rights Reserved.

Loading...done.
(help) for function help.
\q to quit.

:
Try something typing something simple, like "(add 2 2)" (without quotation marks) and hit "ENTER". You should see 4. "add" is a TransLisp function that adds two numbers, but how did George get it to do all that?

Code: Select all

TLisp Shell 3.2.2
Copyright (c) 2001-2014 by Kronosaur Productions, LLC. All Rights Reserved.

Loading...done.
(help) for function help.
\q to quit.

: (add 2 2)
4
:
7) Well, go back to Visual Studio and set a breakpoint (right click on the line of interest to get access to the context menu that should let you set a breakpoint) at the first brace of *CCodeChain::Eval in CodeChain.cpp (currently at line 454, but may not always be the case)

8) Return to the command prompt, and type in "(add 2 2)" -- program execution should now halt at Eval in CodeChain (where you set the breakpoint)

9) Put on your detective hat (which can also be interpreted as more to come soon), and see how the program flows! (press F10 to step over, press F11 to step into, and SHIFT+F11 to step out). If you haven't changed how Visual Studio is setup to display, you should be able to see a "Call Stack" window (In VS Community 2013, usually on the bottom right hand corner). The call stack lists the functions that have been called so far (one by the other), with the most recent call on top, and the oldest call at the bottom. This is helpful in knowing what has been done so far (for instance, if you were wondering *how* "(add 2 2)" became a pItem in the first place.

NOTE: typing "(help)" in TLisp Shell (without the breakpoint set, unless you want to see what happens when you put in the help command) might be of interest too.

NOTE: Setting Transcendence as the StartUp project, and having the breakpoint set when something is interesting is happening in the game could give you insight into how TransLisp functions while the game is running.

NOTE: The README has information on how to use git to keep your local code repositories up-to-date compared with the "master" repositories.

A bit more about TransLisp

TransLisp is a dynamic programming language based on [Lisp](http://en.wikipedia.org/wiki/Lisp_(prog ... _language)). A dynamic programming language is one where the type information of a variable is determined by the compiler at runtime (when the program is executed). Compare this with a static programming languages like C or C++, where one has to explicitly declare the type of variable when creating it.

For instance, in C++, if we want to create an integer variable named integerNumber, we would write:

Code: Select all

int integerNumber = 2
so that when the compiler is reading our code ("compiling"), it reads that integerNumber is of type int.

In TransLisp though, we would write something like:

Code: Select all

(setq  integerNumber 2)
so that when the compiler is compiling our code, it can't figure out what type of variable integerNumber, and doesn't bother to do so. When this line of code is executed, that's when integerNumber is known to the rest of the program as being of integer type.

Essentially what this you don't have to worry about the specifying the type of a variable when you instantiate it, instead, other stuff in the background will take of figuring out what type of variable integerNumber has to be.

Just like Lisp, TransLisp uses "prefix notation", instead of the standard "infix notation", or the uncommon "postfix notation". Recall that "pre" and "post" means "before" and "end" respectively. They refer to the position of the operator symbol, with respect to the position of the arguments (or inputs) to the operator.

We are used to infix notation:

Code: Select all

 2 + 1 = 3
Sometimes, its very useful to use prefix notaiton (for instance, in order to make it easy for compilers to read code files):

Code: Select all

 + 2 1 = 3
The '+' operator was simply written "before" (pre) the notation.

===========================================
===========================================


Here are the types of objects a variable in TransLisp can store:

int32: This is a 32-bit signed integer. Some functions will automatically convert an integer to a string, if necessary. But not all do.

list: This is a list created by (list ...). Note however that empty lists are treated as nil (see below).

nil: Nil is a special type (a boolean, in order for doing boolean algebra -- which can be simply thought of as the algebra of "true" and "false"). Empty lists and empty structures are also considered nil. [Inconsistently, however, empty strings are not considered nil.]

string: This is a character string.

struct: This is a structure (a key-map, which is sort of like a list, except that instead of the objects being indexed by integers, they are indexed by strings (keys)) created with (struct ...).

error: Error is a special type with unique properties. Most of the time, if a function returns an error type, the execution of the caller (the function that executed the current function) is aborted and we return the error all the way up. The exception is (errblock ...) which traps the error.

function: This is a lambda expression, created by (lambda ...).

primitive: This is a built-in function (i.e., one implemented in C++). For example: (typeof typeof) -> primitive (-> is the "output" arrow, and this bit of code can be read as "the type of the function typeof is 'primtive'".

true: This is a special type (a boolean).


===========================================
===========================================

UNDER CONSTRUCTION

Here are the primitive functions:

< or ls:

Code: Select all

(ls a b)
Returns true if a is less than b, Nil otherwise.

Examples:

Code: Select all

: (ls 0 1)
True

Code: Select all

: (ls 0 0)
Nil
Note that if you want to use the symbol <, you would have to still use it using prefix notation:

Examples:

Code: Select all

: (< 0 1)
True

----------------------------------------------------


<= or leq:

Code: Select all

(leq a b)
Returns true if a is less than or equal to b, Nil otherwise.

Examples:

Code: Select all

: (leq 0 1)
True
----------------------------------------------------

> or gr
Usage:

Code: Select all

(gr a b)
Returns true if a is greater than b, Nil otherwise.

Examples:

Code: Select all

: (gr 0 1)
Nil
----------------------------------------------------

>= or geq
Usage:

Code: Select all

(geq a b)
Returns true if a is greater than or equal to b, Nil otherwise.

Examples:

Code: Select all

: (geq 0 1)
Nil
----------------------------------------------------

add
Usage:

Code: Select all

(add x1 x2 ... xn)
Returns the sum of the numbers x1, x2 ..., xn.

Examples:

Code: Select all

: (add 0 1 2 3 4 5 6 7 8 9 10)
55
----------------------------------------------------

abs
Usage:

Code: Select all

(abs x)
Returns the absolute value of the number x.

Examples:

Code: Select all

: (abs -2)
2

----------------------------------------------------

and
Usage:

Code: Select all

(and exp1 exp2 ... expn)
Returns true if all the boolean expressions exp1 to expn are also true, otherwise nil.

Examples:

Code: Select all

: (and true (gr 1 0) true)
True
As mentioned before, an empty list is the same as Nil.

Code: Select all

: (and true (gr 1 0) (list))
Nil
----------------------------------------------------

append
Usage:

Code: Select all

(append L1 L2 ... Ln)
Concatenates (connects back to front) the lists L1, L2, ... Ln.

Code: Select all

: (append (list 1 2 3) (list 4 5 6) (list 8 9 0))
(1 2 3 4 5 6 8 9 0)
----------------------------------------------------

apply

Usage:

Code: Select all

(apply expr arg1 arg2 ... argn list)
Applies an expression (could be a primitive function, or a user created function defined using (lambda ...)) to the arguments arg1, ..., argn. The last argument has to be a list. The last argument has to be a list so that apply always has a handle on how many arguments it should expect (either they are all packaged nicely in a list, or it considers everything before the list an argument, and ignores everything after.

Examples:

Code: Select all

: (apply add 2 2 Nil)
4

Code: Select all

: (apply add (list 2 2))
4

Code: Select all

: (apply add (list 2 2))
4

Code: Select all

: (apply add 2 2)
Last argument for apply must be a list ### (apply add 2 2) ###
----------------------------------------------------

atmAddEntry

Usage:

Code: Select all

(atmAddEntry)
An atom is the opposite of a list (or a struct). Anything that contains sub-values is not an atom. More information to come.

Examples:

Code: Select all

n/a
----------------------------------------------------

atmAddEntry

Usage:

Code: Select all

(atmDeleteEntry)
n/a

Examples:

Code: Select all

n/a
----------------------------------------------------

atmAddEntry

Usage:

Code: Select all

(atmAddEntry)
n/a

Examples:

Code: Select all

n/a
----------------------------------------------------

atmAddEntry

Usage:

Code: Select all

(atmList)
n/a

Examples:

Code: Select all

n/a
----------------------------------------------------

atmLookup

Usage:

Code: Select all

(atmLookup)
n/a

Examples:

Code: Select all

n/a
----------------------------------------------------

atmAtomTable

Usage:

Code: Select all

(atmAtomTable)
n/a

Examples:

Code: Select all

n/a
----------------------------------------------------

block

Usage:

Code: Select all

(block (<possible local variables>) (expr1) (expr2) ... (exprn))
A block connects two or more expressions together. If you only have a single expression (no matter who long) then it doesn’t need a block. For instance:

Code: Select all

(if foo 
   (do-something)
   )

(if foo
   (block ()
      (do-something)
      (do-another-thing)
      )
   )
A switch statement is a single expression, so it doesn’t need a block (unless you need to do something after it):

(if foo
(switch

(more-stuff-in-the-switch)

) ; end of the switch
)

Examples: look for (block ...) statements inside the *.xml files under Transcendence/TransCore.

----------------------------------------------------

cat

Usage:

Code: Select all

(cat s1 s2 ... sn)
Concatenates the strings s1, s2, ... sn.

Examples:

Code: Select all

:(cat "hello" world" "!")
"helloworld!"
----------------------------------------------------

count

Usage:

Code: Select all

(count list)
Count the number of items in the input list

Examples:

Code: Select all

:(count (list 0 1 2))
3
----------------------------------------------------

divide

Usage:

Code: Select all

(divide x y)
Return the result of the integer division of x and y.

Examples:

Code: Select all

: (divide 1 2)
0

Code: Select all

: (divide 2 2)
1
----------------------------------------------------

enum

Usage:

Code: Select all

(enum list itemVar expr)
Walk ("enumerate") through the items in the list one by one, assigning them to the temporary variable itemVar, and using them in the expression expr.

Examples:

Code: Select all

: (setq pot (list))
()
: (enum (list 1 2 3) x (setq pot (append pot x)))
( 1 2 3)
----------------------------------------------------

enumwhile

Usage:

Code: Select all

(enumwhile list condition itemVar expr)
Walk ("enumerate") through the items in the list one by one, assigning them to the temporary variable itemVar, and using them in the expression expr, unless condition evalues to Nil.

Examples:

Code: Select all

: (setq pot (list) )
: (enum (list true true Nil) x (enumwhile (list "hello" " world!" "gobble-d-gook") x y (setq pot (append pot y) ) ) )
Nil
: pot
(hello " world!" gobble-d-gook hello " world!" gobble-d-gook)
----------------------------------------------------

errblock

Usage:

Code: Select all

(errblock )
Like block, but not stopped by errors. (confirm)

Examples:

----------------------------------------------------

error

Usage:

Code: Select all

(errblock msgString)
Create an error type object, with the message string msgString.

Examples:

----------------------------------------------------

eq
Usage:

Code: Select all

(eq a b)
Returns true if a is eq to b, Nil otherwise.

Examples:

Code: Select all

: (eq 0 1)
Nil
----------------------------------------------------

eval
Usage:

Code: Select all

(eval exprString)
Evaluates a quoted expression. The concept of quoting is all about controlling when an expression gets evaluated.

Code: Select all

: (setq myIdentifier 100)
100
: (cat myIdentifier)
100
But what if I want to output “myIdentifier 100”?

Code: Select all

: (cat myIdentifier 100)
100100
That didn’t work because when cat sees “myIdentifier” it treats it like a variable. It tries to evaluate it and returns the result. We need to tell cat to not evaluate that string:

Code: Select all

: (cat ‘myIdentifier 100)
“myIdentifier100”
The single-quote in front of an expression say, don’t evaluate this—treat it like a string. For identifiers (i.e. variable or function names) it is equivalent to:

(cat (quote myIdentifier) 100) -> “myIdentifier100”

However for expressions, one must use (quoted ...), and not ' or " because:

Code: Select all

: (typeof (quote (add 2 2)))
list
: (eval (quote (add 2 2)))
4
: (eval "(add 2 2)")
(add 2 2)


Anyway, returning to our earlier example. What if we want a space between myIdentifier and 100? We need to specify a space character, so we use double-quotes:

(cat “myIdentifier “ 100) -> “myIdentifier 100”

Double-quotes automatically turns the contents into a literal (i.e., treat literally without evaluating). Double-quotes are also the way to create literals with embedded spaces.

The opposite of quote is eval:

myIdentifier -> 100
(quote myIdentifier) -> “myIdentifier”
(eval (quote myIdentifier)) -> 100

Examples:

Code: Select all

: (quote (add 2 2))
(add 2 2)
: (typeof (quote (add 2 2))
list
: (eval (quote (add 2 2)))
4
----------------------------------------------------

filter
Usage:

Code: Select all

(filter list var boolExpr)
Returns those elements of the input list that are able to evaluate boolExpr to True. var is the identifier of the variable (representing an item from the input list) that will be used in writing boolExpr.

Examples:

Code: Select all

: (filter (list 0 10 2 20) x (> x 3))
(10 20)
----------------------------------------------------

----------------------------------------------------

filter
Usage:

Code: Select all

(filter list var boolExpr)
Returns those elements of the input list that are able to evaluate boolExpr to True. var is the identifier of the variable (representing an item from the input list) that will be used in writing boolExpr.

Examples:

Code: Select all

: (filter (list 0 10 2 20) x (> x 3))
(10 20)
----------------------------------------------------

Complete the rest later

{ "find", fnFind, FN_FIND,
"(find source target ['ascending|'descending] [keyIndex]) -> position of target in source (0-based)",
"vv*", 0, },

{ "fncHelp", fnItemInfo, FN_ITEMINFO_HELP, "", NULL, 0, },

----------------------------------------------------

for
Usage:

Code: Select all

(for var start end expr)
Executes expression expr, which contains a reference to variable var, for values of var incremented by 1 between start and less than end.

Examples:

Code: Select all

: (setq pot (list) )
0
: (for x 1 3 (setq pot (append pot (add x 2) ) ) ) 
Nil
: pot
(3 5)
----------------------------------------------------

help
Usage:

Code: Select all

(help partial_name_string) or (help exact_name_string) 
Returns the help string for an exact function, or functions that match partial_name_string, if such a help string exists -- help strings may not exist for all functions. How is this different or similar to fncHelp?

Examples:

Code: Select all


----------------------------------------------------

if
Usage:

Code: Select all

(if boolExpr expr1 expr2) 
If boolExpr evaluates to True, then execute expr1, else execute expr2.

Examples:

Code: Select all


----------------------------------------------------

{ "int", fnItemInfo, FN_ITEMINFO_ASINT, "", NULL, 0, },

----------------------------------------------------

isatom
Usage:

Code: Select all

(isatom expr) or (isatom expr) 
Returns True if expr reduces to atom, Nil otherwise.

Examples:

Code: Select all


----------------------------------------------------

iserror
Usage:

Code: Select all

(iserror expr) 
Returns True if expr reduces to error, Nil otherwise.

Examples:

Code: Select all


----------------------------------------------------

----------------------------------------------------

isint
Usage:

Code: Select all

(isint expr) 
Returns True if expr reduces to int, Nil otherwise.

Examples:

Code: Select all


----------------------------------------------------

isfunction
Usage:

Code: Select all

(isfunction expr) 
Returns True if expr reduces to function, Nil otherwise.

Examples:

Code: Select all


----------------------------------------------------

isprimitive
Usage:

Code: Select all

(isprimitive expr) 
Returns True if expr reduces to primitive, Nil otherwise.

Examples:

Code: Select all


----------------------------------------------------

@
Usage:

Code: Select all

(@ list expr) 
Returns element in list with index that expr reduces to -- thus, expr should reduce to an int.

Examples:

Code: Select all


----------------------------------------------------

----------------------------------------------------

isprimitive
Usage:

Code: Select all

(lambda fnName (A1, ..., An) (expression)) 
Creates a function with name fnName, that takes the arguments between A1, ..., An that may or may not appear in expression.

Examples:

Code: Select all


----------------------------------------------------

{ "lookup", fnFind, FN_LOOKUP,
"(lookup source target ['ascending|'descending] [keyIndex]) -> found entry",
"vv*", 0, },

{ "loop", fnLoop, 0,
"(loop condition exp)",
NULL, 0, },

{ "link", fnLink, 0, "", "s", 0, },
{ "list", fnList, 0,
"(list i1 i2 ... in) -> list",
NULL, 0, },

{ "lnkAppend", fnLinkedListAppend, 0,
"(lnkAppend list item) -> list",
"uv", PPFLAG_SIDEEFFECTS, },

{ "lnkRemove", fnLinkedList, FN_LINKEDLIST_REMOVE,
"(lnkRemove list index) -> list",
NULL, PPFLAG_SIDEEFFECTS, },

{ "lnkRemoveNil", fnLinkedList, FN_LINKEDLIST_REMOVE_NIL,
"(lnkRemoveNil list) -> list",
NULL, PPFLAG_SIDEEFFECTS, },

{ "lnkReplace", fnLinkedList, FN_LINKEDLIST_REPLACE,
"(lnkReplace list index item) -> list",
NULL, PPFLAG_SIDEEFFECTS, },

{ "map", fnMap, 0,
"(map list ['excludeNil|'original|'reduceMax|'reduceMin] var exp) -> list",
"l*qu", 0, },

{ "match", fnMatch, 0,
"(match list var boolean-exp) -> first item that matches",
"lqu", 0, },

{ "max", fnMathList, FN_MATH_MAX,
"(max x1 x2 ... xn) -> z",
"v*", 0, },

{ "min", fnMathList, FN_MATH_MIN,
"(min x1 x2 ... xn) -> z",
"v*", 0, },

{ "modulo", fnMath, FN_MATH_MODULUS,
"(modulo ['degrees] x y) -> z",
"*", 0, },

{ "multiply", fnMathList, FN_MATH_MULTIPLY,
"(multiply x1 x2 ... xn) -> z",
"v*", 0, },

{ "neq", fnEquality, FN_EQUALITY_NEQ, "", NULL, 0, },

{ "not", fnLogical, FN_LOGICAL_NOT,
"(not exp) -> True/Nil",
NULL, 0, },

{ "or", fnLogical, FN_LOGICAL_OR,
"(or exp1 exp2 ... expn) -> True/Nil",
NULL, 0, },

{ "power", fnMathFractions, FN_MATH_POWER,
"(power x y) -> z",
"vv", 0, },

{ "regex", fnRegEx, 0,
"(regex source pattern ['offset|'subex]) -> result",
"ss*", 0, },

{ "quote", fnSpecial, FN_QUOTE,
"(quote exp) -> unevaluated exp",
"u", 0, },

{ "random", fnRandom, FN_RANDOM,
"(random from to)\n(random list)",
"*", 0, },

{ "randomGaussian", fnRandom, FN_RANDOM_GAUSSIAN,
"(randomGaussian low mid high) -> random number between low and high",
"iii", 0, },

{ "randomTable", fnRandomTable, 0,
"(randomTable chance1 exp1 chance2 exp2 ... chancen expn) -> exp",
NULL, 0, },

{ "seededRandom", fnSeededRandom, 0,
"(seededRandom seed from to)\n(seededRandom seed list)",
"i*", 0, },

{ "set", fnSet, FN_SET_SET, "", NULL, PPFLAG_SIDEEFFECTS, },

{ "set@", fnItem, FN_SET_ITEM,
"(set@ list-var index value) -> list\n"
"(set@ struct-var key value) -> struct\n"
"(set@ struct-var struct) -> merged structs",
"uv*", PPFLAG_SIDEEFFECTS, },

{ "setItem", fnItem, FN_SET_ITEM,
"DEPRECATED: Alias of set@",
"uvv", PPFLAG_SIDEEFFECTS, },

{ "setq", fnSet, FN_SET_SETQ, "", NULL, PPFLAG_SIDEEFFECTS, },
{ "shuffle", fnShuffle, 0,
"(shuffle list) -> shuffled list",
"l", 0, },

{ "sort", fnSort, FN_SORT,
"(sort list ['ascending|'descending] [keyIndex]) -> sorted list",
"v*", 0, },

{ "split", fnSplit, 0,
"(split string [characters]) -> list",
"s*", 0, },

{ "sqrt", fnMath, FN_MATH_SQRT,
"(sqrt x) -> z",
"v", 0, },

{ "strCapitalize", fnStrCapitalize,0,
"(strCapitalize string) -> string",
NULL, PPFLAG_SIDEEFFECTS, },

{ "strFind", fnStrFind, 0,
"(strFind string target) -> pos of target in string (0-based)",
"ss", 0, },

{ "subset", fnSubset, 0,
"(subset list pos [count]) -> list",
"vv*", 0, },

{ "subst", fnSubst, 0,
"(subst string arg1 arg2 ... argn) -> string",
"s*", PPFLAG_SIDEEFFECTS, },

{ "subtract", fnMathOld, FN_MATH_SUBTRACT,
"(subtract x y) -> z",
NULL, 0, },

{ "switch", fnSwitch, 0, "", NULL, 0, },

//{ "symDeleteEntry", fnSymTable, FN_SYMTABLE_DELETEENTRY,"", NULL, PPFLAG_SIDEEFFECTS, },

{ "sysGlobals", fnSysInfo, FN_SYSINFO_GLOBALS, "", NULL, 0, },
{ "sysPoolUsage", fnSysInfo, FN_SYSINFO_POOLUSAGE, "", NULL, 0, },
{ "sysTicks", fnSysInfo, FN_SYSINFO_TICKS, "", NULL, 0, },

{ "typeof", fnItem, FN_ITEM_TYPE,
"(typeof item) -> type\n\n"

"type\n\n"

" error\n"
" function\n"
" int32\n"
" list\n"
" primitive\n"
" string\n"
" struct\n",

"v", 0, },

{ "vecVector", fnVecCreate, 0, "", NULL, 0, },
{ "vecSetElement", fnVector, FN_VECTOR_SETELEMENT, "", NULL, PPFLAG_SIDEEFFECTS, }

CodeChain

CodeChain is the project that contains the machinery to parse TransLisp code and then executing it (by calling the underlying C++ implementations corresponding with various TransLisp primitives).

* DefPrimitives.h

* CodeChain.h

* CodeChain.cpp

* Functions.cpp

A walk through Eval

The Eval function, in some ways, is the heart of CodeChain: all TransLisp code, when executed flows through Eval. Why is Eval so important? Eval is the bit of CodeChain that parses a given block of TransLisp and it decides what function to call and what arguments to supply that function call based on its analysis.

Implementing your own datatype for TransLisp

Put together the knowledge obtained in the last few sections to write our own datatype for TransLisp.

Please feel free to ask questions, and let me know what I can do to improve clarity!
Last edited by bzm3r on Tue Feb 10, 2015 9:53 pm, edited 22 times in total.
bzm3r
Militia Lieutenant
Militia Lieutenant
Posts: 100
Joined: Tue Oct 23, 2012 2:38 pm

[reserved]
bzm3r
Militia Lieutenant
Militia Lieutenant
Posts: 100
Joined: Tue Oct 23, 2012 2:38 pm

[reserved]
george moromisato
Developer
Developer
Posts: 2997
Joined: Thu Jul 24, 2003 9:53 pm
Contact:

Thanks for doing this! I'm hope this will encourage people to dive into the source code.
Post Reply