diff --git a/CMakeLists.txt b/CMakeLists.txt index 3320603..7d11c81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(fun VERSION 0.37.27 LANGUAGES C) +project(fun VERSION 0.37.28 LANGUAGES C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) diff --git a/examples/class_test.fun b/examples/class_test.fun new file mode 100755 index 0000000..6be0286 --- /dev/null +++ b/examples/class_test.fun @@ -0,0 +1,30 @@ +#!/usr/bin/env fun + +/* + * This file is part of the Fun programming language. + * https://fun-lang.xyz/ + * + * Copyright 2025 Johannes Findeisen + * Licensed under the terms of the Apache-2.0 license. + * https://opensource.org/license/apache-2-0 + * + * Added: 2025-12-28 + */ + +class Other(number val) + fun _construct(this, val) + this.v = val + +class Test() + fun _construct(this) + val = Other(123) + this.a = val + print("a set") + +t = Test() +print(t.a.v) + +/* Expected output: +a set +123 +*/ diff --git a/examples/data/htdocs/index.html b/examples/data/htdocs/index.html new file mode 100644 index 0000000..df339a0 --- /dev/null +++ b/examples/data/htdocs/index.html @@ -0,0 +1,10 @@ + + + + Fun HTTP Server + + +

Welcome to the Fun HTTP Server!

+

This page is served from ./examples/data/htdocs/index.html.

+ + diff --git a/examples/extra/http_server.fun b/examples/extra/http_server.fun new file mode 100755 index 0000000..0335919 --- /dev/null +++ b/examples/extra/http_server.fun @@ -0,0 +1,22 @@ +#!/usr/bin/env fun + +/* + * This file is part of the Fun programming language. + * https://fun-lang.xyz/ + * + * Copyright 2025 Johannes Findeisen + * Licensed under the terms of the Apache-2.0 license. + * https://opensource.org/license/apache-2-0 + * + * Added: 2025-12-28 + */ + +#include + +port = 8080 +htdocs = "./examples/data/htdocs" + +server = HTTPServer(port) +server.set_htdocs(htdocs) + +server.start() diff --git a/lib/net/http_server.fun b/lib/net/http_server.fun new file mode 100644 index 0000000..cfc49ef --- /dev/null +++ b/lib/net/http_server.fun @@ -0,0 +1,78 @@ +/* + * This file is part of the Fun programming language. + * https://fun-lang.xyz/ + * + * Copyright 2025 Johannes Findeisen + * Licensed under the terms of the Apache-2.0 license. + * https://opensource.org/license/apache-2-0 + * + * Added: 2025-12-28 + */ + +#include +#include + +class HTTPServer(number port) + fun _construct(this, port) + this.port = port + srv = TcpServer(port, 10) + this.server = srv + this.htdocs = "./" + + fun set_htdocs(this, path) + this.htdocs = to_string(path) + + fun start(this) + if (this.server.listen() <= 0) + print("HTTPServer: failed to listen on port " + to_string(this.port)) + return 0 + print("HTTPServer: serving " + this.htdocs + " on port " + to_string(this.port)) + while true + client_fd = this.server.accept() + if (client_fd > 0) + this.handle_client(client_fd) + return 1 + + fun handle_client(this, fd) + request = sock_recv(fd, 4096) + if (len(request) == 0) + sock_close(fd) + return 0 + + // Basic request parsing + lines = str_split(request, "\n") + if (len(lines) == 0) + sock_close(fd) + return 0 + + first_line = lines[0] + parts = str_split(first_line, " ") + if (len(parts) < 2) + sock_close(fd) + return 0 + + method = parts[0] + path = parts[1] + + if (path == "/") + path = "/index.html" + + full_path = this.htdocs + path + content = read_file(full_path) + + if (len(content) > 0) + this.send_response(fd, 200, "OK", content) + else + this.send_response(fd, 404, "Not Found", "

404 Not Found

") + + sock_close(fd) + return 1 + + fun send_response(this, fd, status_code, status_text, body) + resp = "HTTP/1.1 " + to_string(status_code) + " " + status_text + "\r\n" + resp = resp + "Content-Type: text/html\r\n" + resp = resp + "Content-Length: " + to_string(len(body)) + "\r\n" + resp = resp + "Connection: close\r\n" + resp = resp + "\r\n" + resp = resp + body + sock_send(fd, resp) diff --git a/lib/strings.fun b/lib/strings.fun index 47c803a..2ab3e28 100644 --- a/lib/strings.fun +++ b/lib/strings.fun @@ -93,7 +93,7 @@ fun str_replace_all(s, from, to) out = [] number i = 0 while i < n - if (i + lf <= n) && (substr(src, i, lf) == f) + if ((i + lf <= n) && (substr(src, i, lf) == f)) push(out, t) i = i + lf else