Skip to content

Instantly share code, notes, and snippets.

@SeijiEmery
Last active November 5, 2019 20:10
Show Gist options
  • Save SeijiEmery/c75b5cb5b9db9ee696bf7b06927f184a to your computer and use it in GitHub Desktop.
Save SeijiEmery/c75b5cb5b9db9ee696bf7b06927f184a to your computer and use it in GitHub Desktop.
Ideas for a high level game lang
num is pub type where
// static properties (ie. <numtype>.zero, etc)
zero: pub value num
one: pub value num
min: pub value option<num>
max: pub value option<num>
inf: optional pub value option<num>
nan: optional pub value
// operator overloads (using one potential syntax: 'op <bin|un> <symbol>')
op bin +: pub func (a: Self, b: Self) -> Self
op bin -: pub func (a: Self, b: Self) -> Self
op bin *: optional pub func (a: Self, b: Self) -> Self
op bin /: optional pub func (a: Self, b: Self) -> Self
op un -: pub func (a: Self) -> Self
// ternary comparison operator (actually num should just be derived from Cmp/Ord..)
op cmp: pub func (a: Self, b: Self) -> Cmp
// methods...
signof: pub method (@self) -> num
// type constraints: enforce semantics for all number impls
// theoretically could be used on the builtin `num` type to enable compiler optimizations
// on numeric operations for user defined numeric types (as this guarantees that the following
// are / should be equivalent)
requires
0 <==> Self.zero
1 <==> Self.one
2 <==> 1 + 1
_1 <==> 0 - 1
inf <==> Self.inf || Self.nan
// trivial axioms
0 + 0 == 0
0 + 1 == 1
_1 * 1 == _1
_1 * _1 == 1
// nontrivial axioms
forall (a: Self, b: Self)
a + b == b + a
a + 0 == a
a * 1 == a
a / 1 == a
a / 0 == inf * a.signof
if a < 0 then
a.signof == _1
else
a.signof == 1
if a == 0 or b == 0 then
a * b == 0
elif (a < 0 and b < 0) or (a > 0 and b > 0) then
a * b > 0
else
a * b < 0
// vec3 impl. Notably:
// - vec3 is a number
// - vec3 takes a type parameter that is a number
//
vec3 is pub type <T: num = float> deriving num where
x: pub rw T
y: pub rw T
z: pub rw T
// define partial properties for num
// type parameter T is implicitely available since it was defined above
// and is part of any vec3 type instance's type signature
vec3.zero is value vec3(0, 0, 0)
vec3.one is value vec3(1, 1, 1)
vec3.min is value T.min * vec3.one
vec3.max is value T.max * vec3.one
// more vector properties
vec3.fwd is value vec3(1, 0, 0)
vec3.back is value vec3.fwd * -1
// alt syntax 1 for defining operators
// uses explicit types, stating that a has the same type as b...
operator + is pub func <T: num> (a: vec3<T>, b: vec3<T>) -> vec3<T> where
vec3(a.x + b.x, a.y + b.y, a.z + b.z)
// alt syntax 2 for defining operators
// type parameters are implicit, ie assume that
// a.typeof == b.typeof == vec3<T>
// ie. a.typeof.T == b.typeof.T
//
vec3.__add__ is func (a: vec3, b: vec3) where
vec3(a.x + b.x, a.y + b.y, a.z + b.z)
// define a `+=` operator using the above syntax
// @self denotes that a parameter 'self' exists and is this method's object instance
// returning a parameter (@self) instead of a type signature denotes that
// returns a value with that type signature
// should literally return that parameter
// (hence this has an -implicit- `return self` line at the end of this method)
vec3.__adda__ is method (@self: rw vec3, other: vec3) -> @self where
self.x += other.x
self.y += other.y
self.z += other.z
// states that MouseEvent is an event, and that it's a union of other events
// more or less equivalent to saying that
// newtype MouseEvent = MouseMoveEvent | MousePressEvent | MouseScrollEvent
// in other languages
// written using only whitespace b/c
// - we can just define a new language block (ie. `event type`) w/ its own syntax + semantics
// - whitespace only is a lot cleaner
//
MouseEvent is event type of
MouseMoveEvent
MousePressEvent
MouseScrollEvent
MouseKeyboardInputEvent is event type of
MouseEvent
KeyboardEvent
WindowManagerEvent is event type of
MouseKeyboardInputEvent
GamepadInputEvent
GamepadConnectionEvent
WindowMoveEvent
WindowChangeEvent
// events are normally defined concretely like this (note the type of this is just `event`)
MouseMoveEvent is event where
pos: vec2
delta: vec2
MouseButton is enum type of
Left
Right
Middle
MousePressEvent is event where
button: MouseButton
// ECS implementation!!!! :D
// (this is the real reason to have a custom language)
PositionComponent is component of vec3
VelocityComponent is component of vec3
PlayerInputComponent is component where
state: PlayerInputState where
move: vec2
jump: bool
movespeed: num
jumpspeed: num
GravityComponent is component where
gravity: num = GravityInstance.gravity
gravityDir: rot = GravityInstance.gravityDir
terminalVel: num = GravityInstance.terminalVel
TimeInstance is dataparam where
time: Time
dt: Time
MovementSystem is systemtype (exclusive)
PhysicsAffector is systemtype
requires
runafter MovementSystem
runbefore PhysicsSystem
PhysicsSystem is systemtype (exclusive)
PlayerMovementSystem is system deriving MovementSystem of
player: readonly PlayerInputComponent
velocity: rw VelocityComponent
time: read TimeInstance
with
dt = time.dt.seconds
where
velocity.x += dt * player.state.move.x * player.movespeed
if player.state.jump
velocity.y = player.jumpspeed
GravitySystem is system deriving PhysicsAffector of
gravity: GravityComponent
velocity: rw VelocityComponent
time: TimeInstance
where
// split into two vector components:
// vcomponent = vector component along gravityDir
// vortho = vector component perpendicular / orthogonal to gravityDir
// we have a high level language so obviously we can just write a high level fcn on vec3 to express this
let vcomponent, vortho = velocity.splitcomponents(gravity.gravityDir)
let speed = vcomponent.magnitude
speed += Time.dt.seconds * gravity.gravity
speed = min(speed, gravity.terminalVel)
vcomponent = gravity.gravityDir * speed
velocity = vcomponent + vortho
requires
runafter MovementSystem
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment