From 7e322b61ff13011c1fca9dddfb7c3d48f4a0f329 Mon Sep 17 00:00:00 2001 From: tacheraSasi Date: Fri, 6 Dec 2024 18:54:03 +0300 Subject: [PATCH] experimental vintChart vintSpcket --- bar_chart.png | 24 ++++ go.mod | 15 ++- go.sum | 30 +++-- line_graph.png | 24 ++++ module/desktop.go | 255 +++++++++++++++++++++++++++++++++++++++ module/module.go | 10 +- module/vintchart.go | 133 ++++++++++++++++++++ module/vintsocket.go | 121 +++++++++++++++++++ pie_chart.png | 24 ++++ vintLang/desktop.vint | 18 +++ vintLang/vintChart.vint | 7 ++ vintLang/vintSocket.vint | 5 + 12 files changed, 645 insertions(+), 21 deletions(-) create mode 100644 bar_chart.png create mode 100644 line_graph.png create mode 100644 module/desktop.go create mode 100644 module/vintchart.go create mode 100644 module/vintsocket.go create mode 100644 pie_chart.png create mode 100644 vintLang/desktop.vint create mode 100644 vintLang/vintChart.vint create mode 100644 vintLang/vintSocket.vint diff --git a/bar_chart.png b/bar_chart.png new file mode 100644 index 0000000..8ab70b5 --- /dev/null +++ b/bar_chart.png @@ -0,0 +1,24 @@ + + + + + + Awesome go-echarts + + + +
+
+
+ + + diff --git a/go.mod b/go.mod index 1ec4b49..393ed07 100755 --- a/go.mod +++ b/go.mod @@ -8,7 +8,9 @@ require ( github.com/charmbracelet/bubbletea v0.23.2 github.com/charmbracelet/glamour v0.6.0 github.com/charmbracelet/lipgloss v0.7.1 + github.com/go-echarts/go-echarts/v2 v2.4.5 github.com/google/uuid v1.6.0 + github.com/gorilla/websocket v1.5.3 github.com/joho/godotenv v1.5.1 github.com/lrstanley/bubblezone v0.0.0-20230303230241-08f906ff62a9 github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 @@ -37,11 +39,12 @@ require ( github.com/pkg/term v1.2.0-beta.2 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/sahilm/fuzzy v0.1.0 // indirect - github.com/yuin/goldmark v1.5.2 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/yuin/goldmark v1.7.1 // indirect github.com/yuin/goldmark-emoji v1.0.1 // indirect - golang.org/x/net v0.0.0-20221002022538-bcab6841153b // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/term v0.7.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/term v0.20.0 // indirect + golang.org/x/text v0.16.0 // indirect ) diff --git a/go.sum b/go.sum index 0de3fae..c70de64 100755 --- a/go.sum +++ b/go.sum @@ -28,10 +28,14 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/go-echarts/go-echarts/v2 v2.4.5 h1:gwDqxdi5x329sg+g2ws2OklreJ1K34FCimraInurzwk= +github.com/go-echarts/go-echarts/v2 v2.4.5/go.mod h1:56YlvzhW/a+du15f3S2qUGNDfKnFOeJSThBIrVFHDtI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -90,20 +94,24 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.5.2 h1:ALmeCk/px5FSm1MAcFBAsVKZjDuMVj8Tm7FFIlMJnqU= github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= +github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os= github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ= -golang.org/x/net v0.0.0-20221002022538-bcab6841153b h1:6e93nYa3hNqAvLr0pD4PN1fFS+gKzp2zAXqrnTCstqU= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -117,15 +125,15 @@ golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/line_graph.png b/line_graph.png new file mode 100644 index 0000000..6c12700 --- /dev/null +++ b/line_graph.png @@ -0,0 +1,24 @@ + + + + + + Awesome go-echarts + + + +
+
+
+ + + diff --git a/module/desktop.go b/module/desktop.go new file mode 100644 index 0000000..fc1d240 --- /dev/null +++ b/module/desktop.go @@ -0,0 +1,255 @@ +package module + +// import ( +// "fyne.io/fyne/v2" +// "fyne.io/fyne/v2/app" +// "fyne.io/fyne/v2/container" +// "fyne.io/fyne/v2/layout" +// "fyne.io/fyne/v2/widget" +// "fyne.io/fyne/v2/theme" + +// "github.com/ekilie/vint-lang/object" +// ) + +// var DesktopAppFunctions = map[string]object.ModuleFunction{} + +// func init() { +// DesktopAppFunctions["createApp"] = createApp +// DesktopAppFunctions["setTheme"] = setTheme +// DesktopAppFunctions["newLabel"] = newLabel +// DesktopAppFunctions["newButton"] = newButton +// DesktopAppFunctions["newEntry"] = newEntry +// DesktopAppFunctions["newList"] = newList +// DesktopAppFunctions["newCheckbox"] = newCheckbox +// DesktopAppFunctions["newSlider"] = newSlider +// DesktopAppFunctions["newProgressBar"] = newProgressBar +// DesktopAppFunctions["newTabs"] = newTabs +// DesktopAppFunctions["setWindowSize"] = setWindowSize +// DesktopAppFunctions["newImage"] = newImage +// DesktopAppFunctions["addToLayout"] = addToLayout +// DesktopAppFunctions["setTitle"] = setTitle +// DesktopAppFunctions["runApp"] = runApp +// } + +// var appInstance fyne.App +// var mainWindow fyne.Window +// var layoutContainer *fyne.Container + +// // Themes map +// var themeMap = map[string]fyne.Theme{ +// "light": theme.LightTheme(), +// "dark": theme.DarkTheme(), +// "default": theme.DefaultTheme(), +// } + +// func createApp(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 1 { +// return &object.Error{Message: "createApp requires exactly one argument: the app name"} +// } + +// appName := args[0].Inspect() +// appInstance = app.NewWithID(appName) +// mainWindow = appInstance.NewWindow(appName) +// layoutContainer = container.NewVBox() // Default layout +// mainWindow.SetContent(layoutContainer) + +// return &object.Boolean{Value: true} +// } + +// func setTheme(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 1 { +// return &object.Error{Message: "setTheme requires exactly one argument: 'light', 'dark', or 'default'"} +// } + +// themeName := args[0].Inspect() +// selectedTheme, exists := themeMap[themeName] +// if !exists { +// return &object.Error{Message: "Invalid theme name"} +// } + +// fyne.CurrentApp().Settings().SetTheme(selectedTheme) +// return &object.Boolean{Value: true} +// } + +// func newSlider(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 2 { +// return &object.Error{Message: "newSlider requires two arguments: min and max values"} +// } + +// min, ok1 := args[0].(*object.Integer) +// max, ok2 := args[1].(*object.Integer) +// if !ok1 || !ok2 { +// return &object.Error{Message: "Arguments must be numbers"} +// } + +// slider := widget.NewSlider(float64(min.Value), float64(max.Value)) +// layoutContainer.Add(slider) +// return &object.Boolean{Value: true} +// } + +// func newProgressBar(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 1 { +// return &object.Error{Message: "newProgressBar requires one argument: initial value (0.0 - 1.0)"} +// } + +// value, ok := args[0].(*object.Integer) +// if !ok || value.Value < 0.0 || value.Value > 1.0 { +// return &object.Error{Message: "Value must be a number between 0.0 and 1.0"} +// } + +// progressBar := widget.NewProgressBar() +// progressBar.SetValue(value.Value) +// layoutContainer.Add(progressBar) +// return &object.Boolean{Value: true} +// } + +// func newTabs(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args)%2 != 0 { +// return &object.Error{Message: "newTabs requires an even number of arguments: pairs of tab name and tab content"} +// } + +// var tabs []*container.TabItem +// for i := 0; i < len(args); i += 2 { +// tabName := args[i].Inspect() +// tabContent, ok := args[i+1].(*object.String) +// if !ok { +// return &object.Error{Message: "Tab content must be a string"} +// } +// tabs = append(tabs, container.NewTabItem(tabName, widget.NewLabel(tabContent.Value))) +// } + +// tabContainer := container.NewAppTabs(tabs...) +// layoutContainer.Add(tabContainer) +// return &object.Boolean{Value: true} +// } + +// func newLabel(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 1 { +// return &object.Error{Message: "newLabel requires exactly one argument: the text"} +// } + +// labelText := args[0].Inspect() +// label := widget.NewLabel(labelText) +// layoutContainer.Add(label) +// return &object.Boolean{Value: true} +// } + +// func newButton(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 2 { +// return &object.Error{Message: "newButton requires two arguments: the text and a callback"} +// } + +// buttonText := args[0].Inspect() +// callbackFn, ok := args[1].(*object.Function) +// if !ok { +// return &object.Error{Message: "second argument must be a function"} +// } + +// button := widget.NewButton(buttonText, func() { +// callbackFn.Call([]object.Object{}, map[string]object.Object{}) +// }) +// layoutContainer.Add(button) +// return &object.Boolean{Value: true} +// } + +// func newEntry(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 0 { +// return &object.Error{Message: "newEntry requires no arguments"} +// } + +// entry := widget.NewEntry() +// layoutContainer.Add(entry) +// return &object.Boolean{Value: true} +// } + +// func newList(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 1 { +// return &object.Error{Message: "newList requires one argument: a list of strings"} +// } + +// items, ok := args[0].(*object.Array) +// if !ok { +// return &object.Error{Message: "Argument must be a list"} +// } + +// var data []string +// for _, item := range items.Elements { +// data = append(data, item.Inspect()) +// } + +// list := widget.NewList( +// func() int { return len(data) }, +// func() fyne.CanvasObject { return widget.NewLabel("") }, +// func(i widget.ListItemID, o fyne.CanvasObject) { +// o.(*widget.Label).SetText(data[i]) +// }, +// ) +// layoutContainer.Add(list) +// return &object.Boolean{Value: true} +// } + +// func newCheckbox(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 2 { +// return &object.Error{Message: "newCheckbox requires two arguments: the text and a callback"} +// } + +// checkboxText := args[0].Inspect() +// callbackFn, ok := args[1].(*object.Function) +// if !ok { +// return &object.Error{Message: "second argument must be a function"} +// } + +// checkbox := widget.NewCheck(checkboxText, func(checked bool) { +// callbackFn.Call([]object.Object{&object.Boolean{Value: checked}}, map[string]object.Object{}) +// }) +// layoutContainer.Add(checkbox) +// return &object.Boolean{Value: true} +// } + +// func setWindowSize(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 2 { +// return &object.Error{Message: "setWindowSize requires two arguments: width and height"} +// } + +// width, ok1 := args[0].(*object.Integer) +// height, ok2 := args[1].(*object.Integer) +// if !ok1 || !ok2 { +// return &object.Error{Message: "Both arguments must be numbers"} +// } + +// mainWindow.Resize(fyne.NewSize(float32(width.Value), float32(height.Value))) +// return &object.Boolean{Value: true} +// } + +// func newImage(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 1 { +// return &object.Error{Message: "newImage requires one argument: the image file path"} +// } + +// imagePath := args[0].Inspect() +// image := widget.NewImageFromFile(imagePath) +// layoutContainer.Add(image) +// return &object.Boolean{Value: true} +// } + +// func addToLayout(args []object.Object, defs map[string]object.Object) object.Object { +// // Custom logic to allow more advanced layout setups could be added here. +// return &object.Boolean{Value: true} +// } + +// func setTitle(args []object.Object, defs map[string]object.Object) object.Object { +// if len(args) != 1 { +// return &object.Error{Message: "setTitle requires one argument: the title"} +// } + +// title := args[0].Inspect() +// mainWindow.SetTitle(title) +// return &object.Boolean{Value: true} +// } +// func runApp(args []object.Object, defs map[string]object.Object) object.Object { +// if appInstance == nil || mainWindow == nil { +// return &object.Error{Message: "App has not been created. Call createApp first."} +// } +// mainWindow.ShowAndRun() +// return &object.Boolean{Value: true} +// } diff --git a/module/module.go b/module/module.go index 33a6e7a..a501b7d 100755 --- a/module/module.go +++ b/module/module.go @@ -16,8 +16,10 @@ func init() { Mapper["crypto"] = &object.Module{Name: "crypto", Functions: CryptoFunctions} Mapper["regex"] = &object.Module{Name: "regex", Functions: RegexFunctions} Mapper["shell"] = &object.Module{Name: "shell", Functions: ShellFunctions} - Mapper["dotenv"] = &object.Module{Name: "dotenv", Functions: DotenvFunctions} // Corrected - Mapper["sysinfo"] = &object.Module{Name: "sysinfo", Functions: SysInfoFunctions} // Corrected - Mapper["encoding"] = &object.Module{Name: "encoding", Functions: EncodingFunctions} // Corrected - Mapper["colors"] = &object.Module{Name: "colors", Functions: ColorsFunctions} // Corrected + Mapper["dotenv"] = &object.Module{Name: "dotenv", Functions: DotenvFunctions} + Mapper["sysinfo"] = &object.Module{Name: "sysinfo", Functions: SysInfoFunctions} + Mapper["encoding"] = &object.Module{Name: "encoding", Functions: EncodingFunctions} + Mapper["colors"] = &object.Module{Name: "colors", Functions: ColorsFunctions} + Mapper["vintSocket"] = &object.Module{Name: "vintSocket", Functions: VintSocketFunctions} + Mapper["vintChart"] = &object.Module{Name: "vintChart", Functions: VintChartFunctions} } diff --git a/module/vintchart.go b/module/vintchart.go new file mode 100644 index 0000000..803eb36 --- /dev/null +++ b/module/vintchart.go @@ -0,0 +1,133 @@ +package module + +import ( + "bytes" + // "image/png" + "os" + + "github.com/go-echarts/go-echarts/v2/charts" + "github.com/go-echarts/go-echarts/v2/opts" + + "github.com/ekilie/vint-lang/object" +) + +var VintChartFunctions = map[string]object.ModuleFunction{} + +func init() { + VintChartFunctions["barChart"] = barChart + VintChartFunctions["pieChart"] = pieChart + VintChartFunctions["lineGraph"] = lineGraph +} + +// Create a bar chart +func barChart(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 3 { + return &object.Error{Message: "barChart requires three arguments: labels, values, and output file"} + } + + labels := objectArrayToStringSlice(args[0].(*object.Array).Elements) + values := objectArrayToFloatSlice(args[1].(*object.Array).Elements) + output := args[2].Inspect() + + bar := charts.NewBar() + bar.SetGlobalOptions(charts.WithTitleOpts(opts.Title{Title: "Bar Chart"})) + bar.SetXAxis(labels).AddSeries("Values", generateBarData(values)) + + buf := new(bytes.Buffer) + bar.Render(buf) + return saveChartToFile(output, buf.Bytes()) +} + +// Create a pie chart +func pieChart(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 3 { + return &object.Error{Message: "pieChart requires three arguments: labels, values, and output file"} + } + + labels := objectArrayToStringSlice(args[0].(*object.Array).Elements) + values := objectArrayToFloatSlice(args[1].(*object.Array).Elements) + output := args[2].Inspect() + + pie := charts.NewPie() + pie.SetGlobalOptions(charts.WithTitleOpts(opts.Title{Title: "Pie Chart"})) + pie.AddSeries("Values", generatePieData(labels, values)) + + buf := new(bytes.Buffer) + pie.Render(buf) + return saveChartToFile(output, buf.Bytes()) +} + +// Create a line graph +func lineGraph(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 3 { + return &object.Error{Message: "lineGraph requires three arguments: labels, values, and output file"} + } + + labels := objectArrayToStringSlice(args[0].(*object.Array).Elements) + values := objectArrayToFloatSlice(args[1].(*object.Array).Elements) + output := args[2].Inspect() + + line := charts.NewLine() + line.SetGlobalOptions(charts.WithTitleOpts(opts.Title{Title: "Line Graph"})) + line.SetXAxis(labels).AddSeries("Values", generateLineData(values)) + + buf := new(bytes.Buffer) + line.Render(buf) + return saveChartToFile(output, buf.Bytes()) +} + +// Helper functions +func generateBarData(values []float64) []opts.BarData { + data := []opts.BarData{} + for _, v := range values { + data = append(data, opts.BarData{Value: v}) + } + return data +} + +func generatePieData(labels []string, values []float64) []opts.PieData { + data := []opts.PieData{} + for i, v := range values { + data = append(data, opts.PieData{Name: labels[i], Value: v}) + } + return data +} + +func generateLineData(values []float64) []opts.LineData { + data := []opts.LineData{} + for _, v := range values { + data = append(data, opts.LineData{Value: v}) + } + return data +} + +func saveChartToFile(filename string, data []byte) object.Object { + file, err := os.Create(filename) + if err != nil { + return &object.Error{Message: "Failed to create file: " + err.Error()} + } + defer file.Close() + _, err = file.Write(data) + if err != nil { + return &object.Error{Message: "Failed to write file: " + err.Error()} + } + return &object.Boolean{Value: true} +} + +func objectArrayToStringSlice(objects []object.Object) []string { + result := []string{} + for _, obj := range objects { + result = append(result, obj.Inspect()) + } + return result +} + +func objectArrayToFloatSlice(objects []object.Object) []float64 { + result := []float64{} + for _, obj := range objects { + if num, ok := obj.(*object.Integer); ok { + result = append(result, float64(num.Value)) + } + } + return result +} diff --git a/module/vintsocket.go b/module/vintsocket.go new file mode 100644 index 0000000..a067bd0 --- /dev/null +++ b/module/vintsocket.go @@ -0,0 +1,121 @@ +package module + +import ( + "github.com/gorilla/websocket" + "net/http" + "sync" + + "github.com/ekilie/vint-lang/object" +) + +var VintSocketFunctions = map[string]object.ModuleFunction{} + +var upgrader = websocket.Upgrader{ + CheckOrigin: func(r *http.Request) bool { + return true + }, +} + +var connections = struct { + sync.Mutex + clients []*websocket.Conn +}{} + +func init() { + VintSocketFunctions["createServer"] = createServer + VintSocketFunctions["connect"] = connect + VintSocketFunctions["sendMessage"] = sendMessage + VintSocketFunctions["broadcast"] = broadcast +} + +// Create WebSocket server +func createServer(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 1 { + return &object.Error{Message: "createServer requires one argument: port"} + } + + port := args[0].Inspect() + go func() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + return + } + connections.Lock() + connections.clients = append(connections.clients, conn) + connections.Unlock() + + for { + _, msg, err := conn.ReadMessage() + if err != nil { + break + } + conn.WriteMessage(websocket.TextMessage, msg) + } + }) + http.ListenAndServe(":"+port, nil) + }() + + return &object.String{Value: "WebSocket server started on port " + port} +} + +// Connect to WebSocket server +func connect(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 1 { + return &object.Error{Message: "connect requires one argument: URL"} + } + + url := args[0].Inspect() + conn, _, err := websocket.DefaultDialer.Dial(url, nil) + if err != nil { + return &object.Error{Message: "Failed to connect: " + err.Error()} + } + + connections.Lock() + connections.clients = append(connections.clients, conn) + connections.Unlock() + + return &object.String{Value: "Connected to " + url} +} + +// Send message to a specific client +func sendMessage(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 2 { + return &object.Error{Message: "sendMessage requires two arguments: client index and message"} + } + + index := int(args[0].(*object.Integer).Value) + message := args[1].Inspect() + + connections.Lock() + if index >= len(connections.clients) { + connections.Unlock() + return &object.Error{Message: "Client index out of range"} + } + conn := connections.clients[index] + connections.Unlock() + + err := conn.WriteMessage(websocket.TextMessage, []byte(message)) + if err != nil { + return &object.Error{Message: "Failed to send message: " + err.Error()} + } + + return &object.Boolean{Value: true} +} + +// Broadcast message to all clients +func broadcast(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 1 { + return &object.Error{Message: "broadcast requires one argument: message"} + } + + message := args[0].Inspect() + + connections.Lock() + for _, conn := range connections.clients { + conn.WriteMessage(websocket.TextMessage, []byte(message)) + } + connections.Unlock() + + return &object.Boolean{Value: true} +} diff --git a/pie_chart.png b/pie_chart.png new file mode 100644 index 0000000..5c3d876 --- /dev/null +++ b/pie_chart.png @@ -0,0 +1,24 @@ + + + + + + Awesome go-echarts + + + +
+
+
+ + + diff --git a/vintLang/desktop.vint b/vintLang/desktop.vint new file mode 100644 index 0000000..d69bef5 --- /dev/null +++ b/vintLang/desktop.vint @@ -0,0 +1,18 @@ +import desktop + +// Create the desktop application +desktop.createApp() + +// Add a label to the window +desktop.newLabel("Hello, Vint Desktop App!") + +// Add a button with a callback +desktop.newButton("Click Me", fun() { + print("Button clicked!") +}) + +// Add an entry field +desktop.newEntry() + +// Run the application +desktop.runApp() diff --git a/vintLang/vintChart.vint b/vintLang/vintChart.vint new file mode 100644 index 0000000..51561b9 --- /dev/null +++ b/vintLang/vintChart.vint @@ -0,0 +1,7 @@ +import vintChart + +labels = ["A", "B", "C", "D"] +values = [10, 20, 30, 40] +vintChart.barChart(labels, values, "bar_chart.png") +vintChart.pieChart(labels, values, "pie_chart.png") +vintChart.lineGraph(labels, values, "line_graph.png") diff --git a/vintLang/vintSocket.vint b/vintLang/vintSocket.vint new file mode 100644 index 0000000..1da23f6 --- /dev/null +++ b/vintLang/vintSocket.vint @@ -0,0 +1,5 @@ +import vintSocket + +vintSocket.createServer("8080") +vintSocket.connect("ws://localhost:8080") +vintSocket.broadcast("Hello, WebSocket clients!")