Skip to content

Commit

Permalink
[sheet] add postings function
Browse files Browse the repository at this point in the history
  • Loading branch information
ananthakumaran committed Jan 7, 2024
1 parent 062bb8b commit fd36298
Show file tree
Hide file tree
Showing 16 changed files with 191 additions and 84 deletions.
7 changes: 6 additions & 1 deletion internal/server/sheet.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"os"

"github.com/ananthakumaran/paisa/internal/config"
"github.com/ananthakumaran/paisa/internal/query"
"github.com/ananthakumaran/paisa/internal/service"
"github.com/bmatcuk/doublestar/v4"
"github.com/gin-gonic/gin"
"github.com/samber/lo"
Expand All @@ -33,7 +35,10 @@ func GetSheets(db *gorm.DB) gin.H {
files = append(files, readSheetFileWithVersions(dir, path))
}

return gin.H{"files": files}
postings := query.Init(db).All()
postings = service.PopulateMarketPrice(db, postings)

return gin.H{"files": files, "postings": postings}
}

func GetSheet(file SheetFile) gin.H {
Expand Down
62 changes: 61 additions & 1 deletion src/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,66 @@ nav.level.grid-2 {
background-color: $grey-lightest !important;
}

// hightlight
.cm-line {
$hl-yellow: #c99e00;
$hl-orange: #f5871f;
$hl-red: #c82829;
$hl-purple: #8959a8;
$hl-violet: #6c71c4;
$hl-blue: #4271ae;
$hl-cyan: #3e999f;
$hl-green: #718c00;

.tok-heading {
font-weight: bold;
color: $black-ter;
}

.tok-link {
text-decoration: underline;
}

.tok-number {
color: $hl-violet;
font-weight: bold;
}

.tok-string,
.tok-string2 {
color: $hl-red;
}

.tok-keyword {
color: $hl-purple;
}

.tok-comment {
color: $grey;
}

.tok-strong {
font-weight: bold;
}

.tok-typeName {
color: $hl-green;
}

.tok-variableName {
color: $hl-blue;
}

.tok-variableName2 {
color: $hl-cyan;
font-weight: bold;
}

.tok-operator {
color: $hl-orange;
}
}

.cm-line .ͼd {
color: $link;
font-weight: bold;
Expand Down Expand Up @@ -723,7 +783,7 @@ nav.level.grid-2 {
.cm-scroller {
overflow: auto;
font-family: $family-monospace !important;
font-size: 0.928rem;
font-size: 0.9285714285714286rem;
}

.cm-focused {
Expand Down
5 changes: 3 additions & 2 deletions src/lib/editor/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
import { defaultKeymap, history, historyKeymap } from "@codemirror/commands";
import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
import { syntaxHighlighting } from "@codemirror/language";
import { classHighlighter } from "@lezer/highlight";
import { lintKeymap } from "@codemirror/lint";
import { search, searchKeymap } from "@codemirror/search";
import type { Extension } from "@codemirror/state";
Expand All @@ -21,7 +22,7 @@ export const basicSetup: Extension = [
history(),
drawSelection(),
dropCursor(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
syntaxHighlighting(classHighlighter),
autocompletion(),
highlightActiveLine(),
search({ top: true }),
Expand Down
10 changes: 5 additions & 5 deletions src/lib/search_query_editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ function lint(editor: EditorView): Diagnostic[] {
});

if (!hasErrors) {
const ast = buildAST(editor);
const ast = buildAST(editor.state, syntaxTree(editor.state).topNode);

const conditions = ast.clauses.flatMap(collectConditionASTs);
for (const condition of conditions) {
Expand Down Expand Up @@ -254,13 +254,13 @@ function collectDateValueASTs(ast: ClauseAST): DateValueAST[] {
return [];
}

function buildAST(editor: EditorView): QueryAST {
return constructQueryAST(editor.state, syntaxTree(editor.state).topNode);
export function buildAST(state: EditorState, node: SyntaxNode): QueryAST {
return constructQueryAST(state, node);
}

type TransactionPredicate = (transaction: Transaction) => boolean;
export type TransactionPredicate = (transaction: Transaction) => boolean;

function buildFilter(ast: QueryAST): TransactionPredicate {
export function buildFilter(ast: QueryAST): TransactionPredicate {
return andFilter(...ast.clauses.map((clause) => buildFilterFromClauseAST(clause)));
}

Expand Down
31 changes: 12 additions & 19 deletions src/lib/sheet.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import { closeBrackets } from "@codemirror/autocomplete";
import { keymap, type KeyBinding } from "@codemirror/view";
import { history, redoDepth, undoDepth } from "@codemirror/commands";
import {
HighlightStyle,
bracketMatching,
syntaxHighlighting,
defaultHighlightStyle,
syntaxTree
} from "@codemirror/language";
import { bracketMatching, syntaxTree } from "@codemirror/language";
import { lintGutter, linter, type Diagnostic } from "@codemirror/lint";
import { tags } from "@lezer/highlight";
import { keymap, type KeyBinding } from "@codemirror/view";
import { EditorView } from "codemirror";
import _ from "lodash";
export { sheetEditorState } from "../store";
import { sheetEditorState } from "../store";
import { basicSetup } from "./editor/base";
import { sheetExtension } from "./sheet/language";
import { schedulePlugin } from "./transaction_tag";
export { sheetEditorState } from "../store";
import { functions } from "./sheet/functions";

import { buildAST } from "./sheet/interpreter";
import { Environment, buildAST } from "./sheet/interpreter";
import type { Posting } from "./utils";

function lint(editor: EditorView): Diagnostic[] {
const diagnostics: Diagnostic[] = [];
Expand All @@ -41,22 +36,19 @@ function lint(editor: EditorView): Diagnostic[] {
export function createEditor(
content: string,
dom: Element,
postings: Posting[],
opts: {
keybindings?: readonly KeyBinding[];
}
) {
const highlightStyle = HighlightStyle.define(
defaultHighlightStyle.specs.concat([
{ tag: tags.function(tags.variableName), color: "hsl(229, 53%, 53%)" },
{ tag: tags.number, color: "hsl(229, 53%, 53%)", fontWeight: "bold" }
])
);
const env = new Environment();
env.scope = functions;
env.postings = postings;

return new EditorView({
extensions: [
keymap.of(opts.keybindings || []),
basicSetup,
syntaxHighlighting(highlightStyle),
bracketMatching(),
closeBrackets(),
EditorView.contentAttributes.of({ "data-enable-grammarly": "false" }),
Expand All @@ -73,8 +65,9 @@ export function createEditor(
const tree = syntaxTree(viewUpdate.state);
try {
const ast = buildAST(tree.topNode, viewUpdate.state);
results = ast.evaluate();
results = ast.evaluate(env);
} catch (e) {
console.log(e);
// ignore
}
}
Expand Down
15 changes: 12 additions & 3 deletions src/lib/sheet/cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ pi()

Sheet(Line(Expression(FunctionCall(Identifier))))

# Search Query
# Postings Search Query

posting(`amount > 0`)
postings(`amount > 0`)

===>

Sheet(Line(Expression(FunctionCall(Identifier,Arguments(Expression(SearchQueryString(Query(Clause(Condition(Property(Amount),Operator(">"),Value(Number)))))))))))
Sheet(Line(Expression(Postings(SearchQueryString(Query(Clause(Condition(Property(Amount),Operator(">"),Value(Number)))))))))

# Function Definition

Expand All @@ -79,3 +79,12 @@ square(x) = x * 2
===>

Sheet(Line(FunctionDefinition(Identifier,Parameters(Identifier),Expression(BinaryExpression(Expression(Identifier),BinaryOperator,Expression(Literal(Number)))))))


# Empty Postings Search Query

postings(``)

===>

Sheet(Line(Expression(Postings(SearchQueryString(Query)))))
9 changes: 9 additions & 0 deletions src/lib/sheet/functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Posting } from "$lib/utils";
import type { Environment } from "./interpreter";
import { BigNumber } from "bignumber.js";

function cost(env: Environment, ps: Posting[]) {
return ps.reduce((acc, p) => acc.plus(new BigNumber(p.amount)), new BigNumber(0));
}

export const functions = { cost };
7 changes: 5 additions & 2 deletions src/lib/sheet/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export const sheetHighlighting = styleTags({
Header: t.heading,
"FunctionDefinition/Identifier": t.function(t.variableName),
"FunctionCall/Identifier": t.function(t.variableName),
"( )": t.paren,
"= =~ < > <= >=": t.operator
Postings: t.special(t.variableName),
"`": t.heading,
UnaryOperator: t.operator,
BinaryOperator: t.operator,
AssignmentOperator: t.operator
});
39 changes: 27 additions & 12 deletions src/lib/sheet/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ import type { SyntaxNode } from "@lezer/common";
import * as Terms from "./parser.terms";
import type { EditorState } from "@codemirror/state";
import { BigNumber } from "bignumber.js";
import type { SheetLineResult } from "$lib/utils";
import { asTransaction, type Posting, type SheetLineResult } from "$lib/utils";
import {
buildFilter,
buildAST as buildSearchAST,
type TransactionPredicate
} from "$lib/search_query_editor";

const STACK_LIMIT = 1000;

class Environment {
export class Environment {
scope: Record<string, any>;
depth: number;
postings: Posting[];

constructor() {
this.scope = {};
Expand All @@ -17,6 +23,7 @@ class Environment {

extend(scope: Record<string, any>): Environment {
const env = new Environment();
env.postings = this.postings;
env.depth = this.depth + 1;
if (this.depth > STACK_LIMIT) {
throw new Error("Call stack overflow");
Expand Down Expand Up @@ -133,15 +140,18 @@ class FunctionCallAST extends AST {
}
}

class SearchQueryAST extends AST {
readonly value: string;
class PostingsAST extends AST {
readonly predicate: TransactionPredicate;
constructor(node: SyntaxNode, state: EditorState) {
super(node);
this.value = state.sliceDoc(node.firstChild.from, node.firstChild.to);
this.predicate = buildFilter(buildSearchAST(state, node.lastChild.firstChild.nextSibling));
}

evaluate(): any {
return null;
evaluate(env: Environment): any {
return env.postings
.map(asTransaction)
.filter(this.predicate)
.map((t) => t.postings[0]);
}
}

Expand All @@ -153,7 +163,7 @@ class ExpressionAST extends AST {
| BinaryExpressionAST
| ExpressionAST
| FunctionCallAST
| SearchQueryAST;
| PostingsAST;
constructor(node: SyntaxNode, state: EditorState) {
super(node);
switch (node.firstChild.type.id) {
Expand Down Expand Up @@ -185,8 +195,8 @@ class ExpressionAST extends AST {
this.value = new FunctionCallAST(node.firstChild, state);
break;

case Terms.SearchQueryString:
this.value = new SearchQueryAST(node.firstChild, state);
case Terms.Postings:
this.value = new PostingsAST(node.firstChild, state);
break;

default:
Expand Down Expand Up @@ -279,7 +289,10 @@ class LineAST extends AST {
}

evaluate(env: Environment): Record<string, any> {
const value = this.value.evaluate(env);
let value = this.value.evaluate(env);
if (value instanceof BigNumber) {
value = value.toFixed(2);
}
switch (this.valueId) {
case Terms.Assignment:
case Terms.Expression:
Expand All @@ -304,12 +317,13 @@ class SheetAST extends AST {
try {
this.lines.push(new LineAST(node, state));
} catch (e) {
console.log(e);
break;
}
}
}

evaluate(env: Environment = new Environment()): SheetLineResult[] {
evaluate(env: Environment): SheetLineResult[] {
const results: SheetLineResult[] = [];
let lastLineNumber = 0;
for (const line of this.lines) {
Expand All @@ -322,6 +336,7 @@ class SheetAST extends AST {
results.push({ line: line.lineNumber, error: false, ...resultObject } as SheetLineResult);
lastLineNumber++;
} catch (e) {
console.log(e);
results.push({ line: line.lineNumber, error: true, result: e.message });
break;
}
Expand Down
Loading

0 comments on commit fd36298

Please sign in to comment.