diff --git a/src/main.ts b/src/main.ts index fe60fff..4a76306 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,6 +7,7 @@ import { builtins } from './builtins'; import counterApp from './counter.cg?raw'; import stdlibCode from './stdlib.cg?raw'; +import uiComponentsCode from './ui-components.cg?raw'; import textInputCode from './textinput-test.cg?raw'; import testCode from './test.cg?raw'; @@ -15,7 +16,7 @@ canvas.width = 800; canvas.height = 600; document.body.appendChild(canvas); -const cgCode = stdlibCode + '\n' + textInputCode; +const cgCode = stdlibCode + '\n' + uiComponentsCode + '\n' + textInputCode; const tokens = tokenize(cgCode); const parser = new Parser(tokens); diff --git a/src/parser.ts b/src/parser.ts index abfcf78..c2cd626 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -319,17 +319,9 @@ export class Parser { while (true) { if (this.current().kind === 'dot') { - // Record access this.advance(); - const fieldToken = this.expect('ident'); - const field = (fieldToken as { value: string }).value; - expr = { kind: 'record-access', record: expr, field }; - } else if (this.current().kind === 'open-brace') { - if (expr.kind === 'constructor') { - // Constructor application - const record = this.parsePrimary(); - expr = { kind: 'apply', func: expr, args: [record] }; - } else { + + if (this.current().kind === 'open-brace') { // Record update this.advance(); const updates: { [key: string]: AST } = {}; @@ -349,7 +341,21 @@ export class Parser { this.expect('close-brace'); expr = { kind: 'record-update', record: expr, updates } + + } else { + // Record access + const fieldToken = this.expect('ident'); + const field = (fieldToken as { value: string }).value; + expr = { kind: 'record-access', record: expr, field }; } + } else if (this.current().kind === 'open-brace') { + // if (expr.kind === 'constructor') { + // Function / constructor application + const record = this.parsePrimary(); + expr = { kind: 'apply', func: expr, args: [record] }; + // } else { + // break; + // } } else { break; } diff --git a/src/runtime.ts b/src/runtime.ts index acf596a..42a5613 100644 --- a/src/runtime.ts +++ b/src/runtime.ts @@ -16,8 +16,17 @@ export function runApp(app: App, canvas: HTMLCanvasElement) { if (app.view.kind !== 'closure') throw new Error('view must be a function'); + const viewport = { + kind: 'record', + fields: { + width: { kind: 'int', value: canvas.width }, + height: { kind: 'int', value: canvas.height } + } + }; + const callEnv = new Map(app.view.env); callEnv.set(app.view.params[0], state); + callEnv.set(app.view.params[1], viewport); const uiValue = evaluate(app.view.body, callEnv); const ui = valueToUI(uiValue); diff --git a/src/textinput-test.cg b/src/textinput-test.cg index 60d2b61..58ef6be 100644 --- a/src/textinput-test.cg +++ b/src/textinput-test.cg @@ -1,10 +1,11 @@ init = { text = "" }; update = state event \ event - | UpdateText newText \ state { text = newText } - | Submit _ \ state { text = "" }; + | UpdateText newText \ state.{ text = newText } + | Submit _ \ state.{ text = "" }; + # | _ \ state; -view = state \ +view = state viewport \ Column { gap = 20, children = [ @@ -23,6 +24,7 @@ view = state \ onInput = UpdateText, onSubmit = Submit } + # button ({ label = "Go", event = Go }) ] } ]