$MEM_3 = $MEM_1 + $MEM_2
$MEM_1 = $MEM_2
$MEM_2 = $MEM_3
-END
\ No newline at end of file
+ !PRINT($MEM_3, 3 + $MEM_7)
+END
+
+IF !IN_BOUNDS($POS_X + 1, $POS_Y) THEN
+ !SAY($MEM_8)
+END
+
+!REDRAW()
\ No newline at end of file
--- /dev/null
+#version 300 es
+
+precision mediump float;
+
+in vec4 v_col;
+
+out vec4 fragColor;
+
+void main() {
+ fragColor = v_col;
+}
\ No newline at end of file
--- /dev/null
+#version 300 es
+
+layout(location = 0) in vec2 a_pos;
+layout(location = 1) in vec4 a_col;
+
+uniform mat3 u_proj;
+uniform int board_width;
+uniform int board_height;
+
+out vec4 v_col;
+
+void main() {
+ vec2 offset = vec2(gl_InstanceID % board_width, gl_InstanceID / board_width);
+ gl_Position = vec4(u_proj * vec3(a_pos + offset, 1), 1);
+ v_col = a_col;
+}
\ No newline at end of file
--- /dev/null
+import opengl
+import ../gfx/glutils
+
+type
+ LightBoard = ref object
+ width: int
+ height: int
+ data: ref array[1024 * 1024, GLuint]
+ colors: ref array[1024 * 1024 * 4, GLfloat]
+
+ vertexArrayObject: GLuint
+ vertexBufferObject: GLuint
+ indexBufferObject: GLuint
+ colorBufferObject: GLuint
+
+proc CreateBoard*(width, height: int): LightBoard =
+ var data = new(array[1024 * 1024, GLuint])
+ var colors = new(array[1024 * 1024 * 4, GLfloat])
+ for i in 0 ..< (width * height):
+ data[i] = 0x0.GLuint
+ colors[i * 4 + 0] = 0.GLfloat
+ colors[i * 4 + 1] = 0.GLfloat
+ colors[i * 4 + 2] = 0.GLfloat
+ colors[i * 4 + 3] = 1.GLfloat
+ LightBoard(
+ width: width,
+ height: height,
+ data: data,
+ colors: colors
+ )
+
+func GetCol*(board: LightBoard, x, y: int): GLuint =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ 0.GLuint
+ else:
+ board.data[][x + y * board.width]
+
+proc SetCol*(board: LightBoard, x, y: int, val: GLuint) =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ return
+
+ board.data[][x + y * board.width] = val
+ let
+ r = ((val shr 16) and 0xff).GLfloat / 255.GLfloat
+ g = ((val shr 8) and 0xff).GLfloat / 255.GLfloat
+ b = ((val shr 0) and 0xff).GLfloat / 255.GLfloat
+ board.colors[][x * 4 + y * board.width * 4 + 0] = r
+ board.colors[][x * 4 + y * board.width * 4 + 1] = g
+ board.colors[][x * 4 + y * board.width * 4 + 2] = b
+
+func GetA*(board: LightBoard, x, y: int): GLuint =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ 0.GLuint
+ else:
+ (board.data[][x + y * board.width] shr 24) and 0xff
+
+func GetR*(board: LightBoard, x, y: int): GLuint =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ 0.GLuint
+ else:
+ (board.data[][x + y * board.width] shr 16) and 0xff
+
+func GetG*(board: LightBoard, x, y: int): GLuint =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ 0.GLuint
+ else:
+ (board.data[][x + y * board.width] shr 8) and 0xff
+
+func GetB*(board: LightBoard, x, y: int): GLuint =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ 0.GLuint
+ else:
+ (board.data[][x + y * board.width] shr 0) and 0xff
+
+proc SetA*(board: LightBoard, x, y: int, val: GLuint) =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ return
+
+ let mval = val mod 256
+ board.data[][x + y * board.width] = board.data[][x + y * board.width] and 0x00ffffff.GLuint
+ board.data[][x + y * board.width] = board.data[][x + y * board.width] or (mval shl 24)
+
+proc SetR*(board: LightBoard, x, y: int, val: GLuint) =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ return
+
+ let mval = val mod 256
+ board.data[][x + y * board.width] = board.data[][x + y * board.width] and 0xff00ffff.GLuint
+ board.data[][x + y * board.width] = board.data[][x + y * board.width] or (mval shl 16)
+ board.colors[][x * 4 + y * board.width * 4 + 0] = mval.GLfloat / 256.GLfloat
+
+proc SetG*(board: LightBoard, x, y: int, val: GLuint) =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ return
+
+ let mval = val mod 256
+ board.data[][x + y * board.width] = board.data[][x + y * board.width] and 0xffff00ff.GLuint
+ board.data[][x + y * board.width] = board.data[][x + y * board.width] or (mval shl 8)
+ board.colors[][x * 4 + y * board.width * 4 + 1] = mval.GLfloat / 256.GLfloat
+
+proc SetB*(board: LightBoard, x, y: int, val: GLuint) =
+ if x < 0 or y < 0 or x >= board.width or y >= board.height:
+ return
+
+ let mval = val mod 256
+ board.data[][x + y * board.width] = board.data[][x + y * board.width] and 0xffffff00.GLuint
+ board.data[][x + y * board.width] = board.data[][x + y * board.width] or (mval shl 0)
+ board.colors[][x * 4 + y * board.width * 4 + 2] = mval.GLfloat / 256.GLfloat
+
+proc InitRendering*(board: LightBoard) =
+ glGenVertexArrays(1, board.vertexArrayObject.addr)
+ glBindVertexArray(board.vertexArrayObject)
+
+ var vertex_data: array[8, GLfloat] = [
+ 0'f32, 0'f32,
+ 0'f32, 1'f32,
+ 1'f32, 1'f32,
+ 1'f32, 0'f32,
+ ]
+ glGenBuffers(1, board.vertexBufferObject.addr)
+ glBindBuffer(GL_ARRAY_BUFFER, board.vertexBufferObject)
+ glBufferData(GL_ARRAY_BUFFER, vertex_data.sizeof, vertex_data.addr, GL_STATIC_DRAW)
+ glEnableVertexAttribArray(0)
+ glVertexAttribPointer(0, 2, cGL_FLOAT, GL_FALSE, 8.GLsizei, nil)
+
+ glGenBuffers(1, board.colorBufferObject.addr)
+ glBindBuffer(GL_ARRAY_BUFFER, board.colorBufferObject)
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * board.width * board.height, board.colors.addr, GL_DYNAMIC_DRAW)
+ glEnableVertexAttribArray(1)
+ glVertexAttribDivisor(1, 1)
+ glVertexAttribPointer(1, 4, cGL_FLOAT, GL_FALSE, 16.GLsizei, nil)
+
+ var index_data: array[6, GLubyte] = [
+ 0.GLubyte, 1.GLubyte, 2.GLubyte, 0.GLubyte, 2.GLubyte, 3.GLubyte
+ ]
+ glGenBuffers(1, board.indexBufferObject.addr)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, board.indexBufferObject)
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * 6, index_data.addr, GL_STATIC_DRAW)
+
+ glBindVertexArray(0)
+
+ let vertex_shader = glutils.CreateShader(glutils.stVertex, "./data/shaders/board.vert")
+ let fragment_shader = glutils.CreateShader(glutils.stFragment, "./data/shaders/board.frag")
+ let program = glutils.LinkProgram(vertex_shader, fragment_shader)
+ glUseProgram(program)
+
+ let u_board_width = glGetUniformLocation(program, "board_width")
+ let u_board_height = glGetUniformLocation(program, "board_height")
+ let u_proj = glGetUniformLocation(program, "u_proj")
+ glUniform1i(u_board_width, board.width.GLint)
+ glUniform1i(u_board_height, board.height.GLint)
+
+ var proj_mat: array[9, GLfloat] = [
+ (2.GLfloat / board.width.GLfloat).GLfloat, 0.GLfloat, 0.GLfloat,
+ 0.GLfloat, (-2.GLfloat / board.height.GLfloat).GLfloat, 0.GLfloat,
+ -1.GLfloat, 1.GLfloat, 1.GLfloat
+ ]
+ glUniformMatrix3fv(u_proj, 1.GLsizei, GL_FALSE, proj_mat[0].addr)
+
+proc RebufferColors*(board: LightBoard) =
+ glBindBuffer(GL_ARRAY_BUFFER, board.colorBufferObject)
+ glBufferSubData(GL_ARRAY_BUFFER, 0.GLintptr, sizeof(GLfloat) * 4 * board.width * board.height, board.colors[].addr)
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
+
+proc Render*(board: LightBoard) =
+ glBindVertexArray(board.vertexArrayObject)
+ glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nil, (board.width * board.height).GLsizei)
+ glBindVertexArray(0)
\ No newline at end of file
import os
import sequtils
import opengl
+import random
import glfw3 as glfw
import gfx/window as gfx_window
import gfx/glutils as glutils
import lang/parser as parser
import lang/tokens
+import board/board
+
proc key_down(window: glfw.Window, key, scancode, action, modifier: cint) {.cdecl.} =
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
glfw.SetWindowShouldClose(window, glfw.TRUE)
proc main2() =
let window = gfxWindow.NewWindow(800, 600, "ASDF")
-
window.SetKeyCallback(key_down)
- var version = cast[cstring](glGetString(GL_VERSION))
- echo $version
-
let vertex_shader = glutils.CreateShader(glutils.stVertex, "./data/shaders/basic.vert")
let fragment_shader = glutils.CreateShader(glutils.stFragment, "./data/shaders/basic.frag")
let program = glutils.LinkProgram(vertex_shader, fragment_shader)
glBindVertexArray(0)
+
+proc main() =
+ let window = gfxWindow.NewWindow(1200, 700, "ASDF")
+ window.SetKeyCallback(key_down)
+
+ let source_code = readFile("data/progs/test.lgt")
+ let tokens = toSeq(lexer.GenerateTokens(source_code))
+ for exp in parser.ParseTokens(tokens):
+ echo exp
+
+ let board = CreateBoard(256, 256)
+ board.InitRendering()
+
while not window.ShouldClose():
glClearColor(0, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT)
- glBindVertexArray(vao)
- glDrawElementsInstanced(GL_TRIANGLES, 3.GLsizei, GL_UNSIGNED_INT, nil, 2)
- glBindVertexArray(0)
+ board.SetCol(random.rand(256), random.rand(256), random.rand(0xffffff).GLuint)
+
+ board.RebufferColors()
+ board.Render()
+ os.sleep(1)
window.Refresh()
window.CloseWindow()
-proc main() =
- let source_code = readFile("data/progs/test.lgt")
- let tokens = toSeq(lexer.GenerateTokens(source_code))
- for token in tokens:
- echo token
-
- echo "\n\n\n"
-
- for exp in parser.ParseTokens(tokens):
- echo exp
-
when isMainModule:
main()
type
LightExprType* = enum
- leNull = 0,
- leVar = 1,
- leNumLit = 2,
- leOp = 3,
- leAssign = 4,
- leLabel = 5,
- leGoto = 6,
- leIf = 7,
- leWhile = 8,
- leBreak = 9
+ leNull = 0,
+ leVar = 1,
+ leNumLit = 2,
+ leOp = 3,
+ leAssign = 4,
+ leLabel = 5,
+ leGoto = 6,
+ leIf = 7,
+ leWhile = 8,
+ leBreak = 9,
+ leFuncCall = 10,
LightExpr* = ref object
case kind*: LightExprType
of leIf, leWhile:
condition*: LightExpr
body*: seq[LightExpr]
+ of leFuncCall:
+ func_name*: string
+ params*: seq[LightExpr]
else:
discard
of leIf: "If[" & $exp.condition & " -> " & $exp.body & "]"
of leWhile: "While[" & $exp.condition & " -> " & $exp.body & "]"
of leBreak: "Break"
+ of leFuncCall: "FuncCall[" & exp.func_name & ", " & $exp.params & "]"
else: ""
\ No newline at end of file
import ./tokens
iterator Generate_tokens*(source: string): LightToken =
- for token, is_sep in strutils.tokenize(source, {' ', '\n', ';', '\t', '='}):
+ for token, is_sep in strutils.tokenize(source, {' ', '\n', ';', '\t', '=', ',', '(', ')'}):
if is_sep:
- if token.contains({'\n', ';'}):
- yield LightToken(kind: ltExprDelim)
if token.contains({'='}):
yield LightToken(kind: ltEq)
+ if token.contains({','}):
+ yield LightToken(kind: ltParamDelim)
+ if token.contains({'('}):
+ yield LightToken(kind: ltParamStart)
+ if token.contains({')'}):
+ yield LightToken(kind: ltParamEnd)
+ if token.contains({'\n', ';'}):
+ yield LightToken(kind: ltExprDelim)
continue
if token.startsWith('$'):
- let varString = token[1 .. ^1]
+ let varString = token[1 .. ^1].toLowerAscii
var varName: LightVariable
if varString == "":
raise newException(IOError, "Expected variable name")
else:
- if varString == "MEM_1": varName = var1
- elif varString == "MEM_2": varName = var2
- elif varString == "MEM_3": varName = var3
- elif varString == "MEM_4": varName = var4
- elif varString == "MEM_5": varName = var5
- elif varString == "MEM_6": varName = var6
- elif varString == "MEM_7": varName = var7
- elif varString == "MEM_8": varName = var8
+ if varString == "mem_1": varName = var1
+ elif varString == "mem_2": varName = var2
+ elif varString == "mem_3": varName = var3
+ elif varString == "mem_4": varName = var4
+ elif varString == "mem_5": varName = var5
+ elif varString == "mem_6": varName = var6
+ elif varString == "mem_7": varName = var7
+ elif varString == "mem_8": varName = var8
+ elif varString == "pos_x": varName = var9
+ elif varString == "pos_y": varName = var10
else:
raise newException(IOError, "Invalid variable name.")
yield LightToken(kind: ltVar, var_name: varName)
+ elif token.startsWith('!'):
+ let funcName = token[1..^1].toLowerAscii
+ yield LightToken(kind: ltFunc, func_name: funcName)
+
elif token == "=":
yield LightToken(kind: ltEq)
import ../utils/iter
type
- LightParser* = object
+ LightParser = object
tokens: Iter[LightToken]
-func CreateParser*(tokens: Iter[LightToken]): LightParser =
+func CreateParser(tokens: Iter[LightToken]): LightParser =
LightParser(tokens: tokens)
-func CreateParser*(tokens: seq[LightToken]): LightParser =
+func CreateParser(tokens: seq[LightToken]): LightParser =
CreateParser(CreateIter[LightToken](tokens, LightToken(kind: ltNull)))
-func NextExpr*(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]): LightExpr
+func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]): LightExpr
-func Parse_block(tokens: Iter[LightToken]): seq[LightExpr] =
+func Parse_block(tokens: Iter[LightToken], sep, endd: LightTokenType): seq[LightExpr] =
result = @[]
var last = tokens.Current
- if last.kind == ltBlockEnd:
+ if last.kind == endd:
tokens.Step()
return
var parser = CreateParser(tokens)
- while last.kind != ltBlockEnd:
- let p = parser.NextExpr(LightExpr(kind: leNull), {ltExprDelim, ltBlockEnd})
+ while last.kind != endd:
+ let p = parser.NextExpr(LightExpr(kind: leNull), {sep, endd})
if p.kind != leNull:
result.add(p)
last = parser.tokens.Current
parser.tokens.Step()
-func NextExpr*(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]): LightExpr =
+func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]): LightExpr =
let curr = parser.tokens.Current
if curr.kind in stop_at:
if prev.kind != leVar:
raise newException(ValueError, "Expected variable on the left of assignment operator")
- let next = parser.NextExpr(LightExpr(kind: leNull), stop_at)
+ else:
+ let next = parser.NextExpr(LightExpr(kind: leNull), stop_at)
- return LightExpr(
- kind: leAssign,
- variable: prev.var_name,
- expression: next
- )
+ return LightExpr(
+ kind: leAssign,
+ variable: prev.var_name,
+ expression: next
+ )
elif curr.kind == ltLabel:
return LightExpr(
let next = parser.tokens.Current
if next.kind != ltLabel:
raise newException(ValueError, "Expected label after goto")
-
- return LightExpr(
- kind: leGoto,
- label: next.label_name
- )
+
+ else:
+ return LightExpr(
+ kind: leGoto,
+ label: next.label_name
+ )
elif curr.kind == ltIf:
let condition = parser.NextExpr(LightExpr(kind: leNull), {ltBlockStart})
parser.tokens.Step()
- let body = Parse_block(parser.tokens)
+ let body = Parse_block(parser.tokens, ltExprDelim, ltBlockEnd)
return LightExpr(
kind: leIf,
elif curr.kind == ltWhile:
let condition = parser.NextExpr(LightExpr(kind: leNull), {ltBlockStart})
parser.tokens.Step()
- let body = Parse_block(parser.tokens)
+ let body = Parse_block(parser.tokens, ltExprDelim, ltBlockEnd)
return LightExpr(
kind: leWhile,
return LightExpr(
kind: leBreak
)
+
+ elif curr.kind == ltFunc:
+ if parser.tokens.Current.kind != ltParamStart:
+ raise newException(ValueError, "Expected parameter list after function call")
+
+ parser.tokens.Step()
+ let params = Parse_block(parser.tokens, ltParamDelim, ltParamEnd)
+
+ return LightExpr(
+ kind: leFuncCall,
+ func_name: curr.func_name,
+ params: params
+ )
iterator Parse_tokens*(tokens: seq[LightToken]): LightExpr =
var parser = CreateParser(tokens)
ltVar, ltNum,
ltExprDelim,
ltLabel, ltGoto,
- ltIf, ltWhile, ltBlockStart, ltBlockEnd,
+ ltIf, ltWhile,
+ ltBlockStart, ltBlockEnd,
ltBreak,
+ ltFunc,
+ ltParamStart, ltParamEnd,
+ ltParamDelim,
ltOp, ltEq
LightToken* = ref object
value*: LightInt
of ltLabel:
label_name*: string
+ of ltFunc:
+ func_name*: string
of ltOp:
operation*: LightOperation
else:
of var6: "MEM_6"
of var7: "MEM_7"
of var8: "MEM_8"
+ of var9: "POS_X"
+ of var10: "POS_Y"
proc `$`*(token: LightToken): string =
return
of ltBreak: "BreakToken"
of ltBlockStart: "BlockStartToken"
of ltBlockEnd: "BlockEndToken"
- of ltOp: "OpeartionToken[" & $token.operation & "]"
\ No newline at end of file
+ of ltFunc: "FunctionToken[" & token.func_name & "]"
+ of ltParamStart: "ParamStartToken"
+ of ltParamEnd: "ParamEndToken"
+ of ltParamDelim: "ParamDelimToken"
+ of ltOp: "OpeartionToken[" & $token.operation & "]"
+ else: "UndefinedToken"
\ No newline at end of file
type
LightVariable* = enum
var1 = 0, var2 = 1, var3 = 2, var4 = 3,
- var5 = 4, var6 = 5, var7 = 6, var8 = 7
+ var5 = 4, var6 = 5, var7 = 6, var8 = 7,
+ var9 = 8, var10 = 9
LightOperation* = enum
loAdd, loSub, loMul, loDiv, loMod,