Skip to content

Instantly share code, notes, and snippets.

@SanderMertens
Last active May 27, 2021 06:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SanderMertens/cb53ed19564a69a738a9855502d82b69 to your computer and use it in GitHub Desktop.
Save SanderMertens/cb53ed19564a69a738a9855502d82b69 to your computer and use it in GitHub Desktop.
// - each expression has a type & an optional value.
//
// - if the expression is an integer literal:
// - the type is Integer
// - the value is the integer value
//
// - if the expression is an floating point literal:
// - the type is Float
// - the value is the integer value
//
// - if the expression is an argument list, the type is a Type<args = argument list>
//
// - if the expression is of an unknown/unspecified type, the type is undefined
//
// - any program with variables/values of an undefined type cannot be executed
//
// - if the expression is a literal, its type is partially defined
//
// - a program may contain partially defined types, as long as they can be
// resolved to fully defined types where used
//
// - if the expression is a function (identifier + argument list):
// - the type is Type<kind = Function, args = argument list>
// - the value is the function
//
// - if the expression is a complete function call:
// - the type is the function return type
// - if the function has no body the returntype is the function
//
// - if the expression is an incomplete function call:
// - the type is the function type minus the provided arguments
// - the value is a partially constructed function call
//
// - if the expression is a function A that is assigned to a function B,
// the arguments of function A are matched & passed by name to function B
// when function A is called
//
// - when an untyped value (literal, initializer list) is assigned to a typed
// variable, the type function is called with the value before it is assigned.
//
// - when an untyped value (literal, initializer list) is assigned to an
// untyped variable, the variable assumes the equivalent type of the value.
//
// - when an untyped value is passed to a parameter of a function, it is
// as if the value is assigned to a variable of the type of the parameter.
//
// - if a type's argument list contains one or more named arguments, literal
// values of that type must use an initializer list, e.g. { }
// Example: position(int x, int y); position p = {10, 20}
//
// - if a type's argument list contains a single unnamed argument, literal
// values for that type should not use an initializer list
// Example: int(int); int i = 10;
//
// - a function contains zero or more immutable key-value pairs, written inside
// of < >
//
// - the function name together with the key-value pairs uniquely identify a
// function
//
// - key-value pairs may be added to a function, which creates a new function
//
// - each key may only occur once in the list
//
// - keys may be forward declared without a value
//
// - a forward declared key that is not assigned a value behaves as if the key
// does not exist when accessed by value but cannot be forward declared again
//
// - keys may be forward declared with an undefined value
//
// - a function that contains keys with undefined values cannot be called
//
// - a program that has one or more keys with undefined values cannot be ran.
//
// - two types with the same base but different key-value pairs are assignable
// as long as overlapping keys match
//
// - a type is always assignable to itself
//
// - a variable may always be assigned a value as long as its type is assignable
//
// - a function with argument types that have undefined keys is undefined
//
// - when an undefined function is (partially) called, the types of the provided arguments
// must specify defined values for the undefined keys.
//
// - when one or more undefined keys are deduced from function arguments, the type of
// the resulting expression will be the original function type where the deduced
// key values will have replaced the undefined values.
//
// Type bootstrap
Type<kind = undefined>()
// type == Type<kind = Function, args = ()>
// value == Type<kind = undefined>
// Bootstrap function for number types
Number<kind = undefined> = Type<kind = Number<kind = kind>>
// type == Type<kind = Function, args = ()>
// value == Number<kind = undefined> == Type<kind = Number<kind = undefined>>
// Bootstrap function for integer type
Integer(Integer) = Number<Integer>
// type == Type<kind = Function, args = (Integer)>
// value == Integer == Number<Integer> == Type<kind = Number<Integer>>
// Bootstrap function for float type
Float(Float) = Number<Float>
// type == Type<kind = Function, args = (Float)>
// value == Float == Number<Float> == Type<kind = Number<Float>>
i = 10
// type == Integer
// value == Integer(10) == 10
l = {10, 20}
// type = Type<kind = Initializer>
// value = {10, 20}
int = Integer
// type == Type<kind = Function, args = (Integer)>
// value == Integer == int
i = int(10)
// type == int == Integer
// value == int(10) == 10
a = (int x, int y)
// type == Type<args = (int x, int y)>
position(int x, int y)
// type == Type<kind = Function, args = (int x, int y)>
// value === position
position_10 = position(10)
// type == Type<kind = Function, args = (int y)>
// value === position(x = 10)
p = position(10, 20)
// type == position
// value === position(x = 10, y = 20)
p = position_10(20)
// type == position
// value === position(x = 10, y = 20)
position_3d(int x, int y, int z) = position(int x, int y)
// type == Type<kind = Function, args = (position(int x, int y), int z)>
// value === position_3d
p = position_3d(10)
// type == Type<kind = Func, args = (position(int y), int z)>
// value === position_3d(x = 10)
p = position_3d(10, 20)
// type == Type<kind = Func, args = (int z)>
// value === position_3d(x = 10, y = 20)
p = position_3d(10, 20, 30)
// type == position_3d
// value === position_3d(x = 10, y = 20, z = 30)
p = position_3d(position(10, 20), 30)
// type == position_3d
// value === position_3d(x = 10, y = 20, z = 30)
line(int x1, int y1, int x2, int y2) = (position(int x1, int x1), position(int x2, int y2))
// type == Type<kind = Function, args = (position(int x1, int y1), position(int x2, int y2))>
// value == line
l = line(10, 20, 30, 40)
// type == line
// value === line(10, 20, 30, 40)
line(position start, position stop)
// type == Type<kind = Function, args = (start = position(int x, int y), stop = position(int x, int y))>
l_xyx = line({10, 20}, {30})
// type == Type<kind = Function, args = (stop = position(int y))>
// value === line(start = {x = 10, y = 20}, stop = {x = 30})
l_stop = line(stop = {30, 40})
// type == Type<kind = Function, args = (start = position(int x, int y))>
// value === line(stop = {30, 40})
l = l_xyx(stop = {40})
// type == line
// value === line({10, 20}, {30, 40})
l = l_stop({10, 20})
// type == line
// value === line({10, 20}, {30, 40})
red_line = line<color = Red>
// type == Type<kind = Function, args = (position(int x1, int y1), position(int x2, int y2))>
// value == line<color = Red>
rl = red_line({10, 20}, {30, 40})
// type == line<color = Red>
// value == line<color=Red>({10, 20}, {30, 40})
flip(line l) {
return line(l.stop, l.start)
}
// type == Type<kind = Function, args = (line l)>
// value = line
flip(line l) = line(l.stop, l.start)
// same
f = flip(l)
// type = line
// value = line({30, 40}, {10, 20})
sum(Number a, Number b) {
return a + b
}
// type = Type<kind = Function, args = (Number<kind = undefined> a, Number<kind = undefined> b)>
// value = Number<kind = undefined>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment