Skip to content

Commit

Permalink
socket library example inside Lib/socket/lib.bic
Browse files Browse the repository at this point in the history
This is just an idea for a module system for bichara. Anyway, it is starting to look a lot more like a 'professional' programming language
  • Loading branch information
rigel-star committed Oct 22, 2024
1 parent 03bae55 commit b6ebb58
Show file tree
Hide file tree
Showing 17 changed files with 317 additions and 113 deletions.
6 changes: 6 additions & 0 deletions Bich/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

BUILD_PATH=../

gcc -c -Wall -Werror -fpic sock.c
gcc -shared -o $BUILD_PATH/libbich.so sock.o
20 changes: 8 additions & 12 deletions examples/sock.c → Bich/sock.c
Original file line number Diff line number Diff line change
@@ -1,52 +1,49 @@
// Server side C program to demonstrate Socket
// programming
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdint.h>

typedef int32_t Bich_Int;

struct sockaddr_in address;
socklen_t addrlen;

void sock_close(int fd) {
void __BICH_POSIX__close_socket(Bich_Int fd) {
close(fd);
}

void sock_write(int fd, const char* msg, int size) {
void __BICH_POSIX__write_socket(Bich_Int fd, const char* msg, Bich_Int size) {
send(fd, msg, size, 0);
}

void sock_listen(int fd, int backlog) {
void __BICH_POSIX__listen_socket(Bich_Int fd, Bich_Int backlog) {
if (listen(fd, backlog) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
puts("Socket listen");
}

int sock_accept(int fd) {
Bich_Int __BICH_POSIX__accept_socket_conn(Bich_Int fd) {
int new_socket = accept(fd, (struct sockaddr*)&address, &addrlen);
if (new_socket < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
puts("New socket connection accepted");
return new_socket;
}

int sock(int port) {
Bich_Int __BICH_POSIX__create_socket(Bich_Int port) {
int opt = 1;
addrlen = sizeof(address);
char buffer[1024] = { 0 };

int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
puts("Socket open");

if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
perror("setsockopt");
Expand All @@ -60,6 +57,5 @@ int sock(int port) {
perror("bind failed");
exit(EXIT_FAILURE);
}
puts("Socket bound");
return server_fd;
}
1 change: 1 addition & 0 deletions Lib/http/lib.bic
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import socket;
84 changes: 84 additions & 0 deletions Lib/socket/lib.bic
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Creates a POSIX environment socket and returns a file
// descriptor for that socket.
//
// Arguments:
// port: Port to bind the socket to.
def extern __BICH_POSIX__create_socket(port: integer) -> integer;

// Listens for incoming connections on the specified socket file descriptor.
//
// Arguments:
// fd: The file descriptor for the socket.
// backlog: The maximum length of the queue for pending connections.
def extern __BICH_POSIX__listen_socket(fd: integer, backlog: integer) -> void;

// Accepts an incoming connection on the specified socket file descriptor.
//
// Arguments:
// fd: The file descriptor for the socket.
//
// Returns: A new file descriptor for the accepted connection.
def extern __BICH_POSIX__accept_socket_conn(fd: integer) -> integer;

// Writes a message to the specified socket file descriptor.
//
// Arguments:
// fd: The file descriptor for the socket.
// msg: The message to be sent over the socket.
// size: The size of the message in bytes.
def extern __BICH_POSIX__write_socket(fd: integer, msg: str, size: integer) -> void;

// Closes the specified socket file descriptor.
//
// Arguments:
// fd: The file descriptor for the socket to be closed.
def extern __BICH_POSIX__close_socket(fd: integer) -> void;

// Create a socket
def create_socket(port: integer) -> integer {
if (port < 0) {
return 0;
}
if (port > 65535) {
return 0;
}
return __BICH_POSIX__create_socket(port);
}

def listen_socket(fd: integer, backlog: integer) -> void {
if (fd < 0) {
return;
}
__BICH_POSIX__listen_socket(fd);
}

def accept_socket(fd: integer) -> integer {
if (fd < 0) {
return 0;
}
return __BICH_POSIX__accept_socket_conn(fd);
}

def write_socket(fd: integer, msg: str, size: integer) -> void {
if (fd < 0) {
return;
}
__BICH_POSIX__write_socket(fd, msg, size);
}

def close_socket(fd: integer) -> void {
__BICH_POSIX__close_socket(fd);
}

def main() -> void {
let fd: integer = create_socket(8080);
listen_socket(fd, 3);

loop {
let new_fd: integer = accept_socket(fd);
let http_response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 25\r\n\r\n<b>Hello from Bichara</b>";
write_socket(new_fd, http_response, 90);
close_socket(new_fd);
}
close_socket(fd);
}
Empty file added Lib/std/lib.bic
Empty file.
1 change: 1 addition & 0 deletions examples/input1.bic
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// this is a comment
def extern sock(port: integer) -> integer;
def extern sock_listen(fd: integer, backlog: integer) -> void;
def extern sock_accept(fd: integer) -> integer;
Expand Down
9 changes: 9 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh

BICH_STD_LIB_PATH=.

RUST_BACKTRACE=1 cargo run 1> main.S
gcc -o out main.S -L$BICH_STD_LIB_PATH -lbich

export DYLD_LIBRARY_PATH=./:$DYLD_LIBRARY_PATH
./out
6 changes: 3 additions & 3 deletions src/code_gen/aarch64/aarch64_codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> {
Ok(NO_REG)
}

fn gen_loop_stmt(&mut self, ast: &AST) -> Result<usize, CodeGenErr> {
fn gen_loop_stmt(&mut self, ast: &AST) -> CodeGenResult {
// loop start label
let label_start: usize = self.get_next_label();

Expand All @@ -271,7 +271,7 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> {
Ok(NO_REG)
}

fn gen_break_stmt(&mut self, break_label: usize) -> Result<usize, CodeGenErr> {
fn gen_break_stmt(&mut self, break_label: usize) -> CodeGenResult {
println!("b _L{}", break_label);
Ok(NO_REG)
}
Expand Down Expand Up @@ -402,7 +402,7 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> {
Ok(r1)
}

fn gen_return_stmt(&mut self, result_reg: usize, early_return: bool) -> CodeGenResult {
fn gen_return_stmt(&mut self, early_return: bool) -> CodeGenResult {
// NOTE: Generate code depending on the function's type. i.e. use w0 for i32, x0 for i64 etc.
// let func_ret_type: LitTypeVariant = self.sym_table.get_symbol(func_id).lit_type;
// is it an early return?
Expand Down
12 changes: 8 additions & 4 deletions src/code_gen/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,14 @@ pub trait CodeGen {
else if ast_node.operation == ASTOperation::AST_RETURN {
let early_return = parent_ast_kind != ASTOperation::AST_FUNCTION;
let possible_ret_stmt: Stmt = ast_node.kind.clone().unwrap_stmt();
let return_expr: &AST = ast_node.left.as_ref().unwrap();
let result_reg: usize = self.gen_expr(&return_expr.kind.clone().unwrap_expr(), ast_node.operation, reg, parent_ast_kind)?;
return match possible_ret_stmt {
Stmt::Return(_) => self.gen_return_stmt(result_reg, early_return),
Stmt::Return(_) => {
if ast_node.left.is_some() {
let return_expr: &AST = ast_node.left.as_ref().unwrap();
_ = self.gen_expr(&return_expr.kind.clone().unwrap_expr(), ast_node.operation, reg, parent_ast_kind)?;
}
self.gen_return_stmt(early_return)
}
_ => Ok(NO_REG)
};
}
Expand Down Expand Up @@ -351,7 +355,7 @@ pub trait CodeGen {

fn gen_array_access2(&mut self, symbol_id: usize, index: usize) -> CodeGenResult;

fn gen_return_stmt(&mut self, result_reg: usize, early_return: bool) -> CodeGenResult;
fn gen_return_stmt(&mut self, early_return: bool) -> CodeGenResult;

fn gen_func_call_stmt(&mut self, func_call_stmt: &FuncCallStmt) -> CodeGenResult;

Expand Down
18 changes: 6 additions & 12 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub enum BErrType {
NonSubscriptable,
NonCallable,
SymbolAlreadyDefined,
MissingReturnType,
TypeError(BTypeErr),
None
}
Expand All @@ -88,6 +89,7 @@ impl BErr {
BErrType::NonSubscriptable => "Identifier is not subscriptable".to_string(),
BErrType::NonCallable => "Identifier is not callable".to_string(),
BErrType::SymbolAlreadyDefined => "Symbol already defined".to_string(),
BErrType::MissingReturnType => "Missing return type".to_string(),
BErrType::TypeError(ref type_error) => match type_error {
BTypeErr::TypesMismatch { expected, found } => format!("Type mismatch: expected {}, found {}", expected, found),
BTypeErr::AssignmentTypeMismatch { var_type, assigned_type } => format!("Cannot assign a value of type '{}' to a variable of type '{}'", assigned_type, var_type),
Expand Down Expand Up @@ -141,26 +143,18 @@ impl BErr {
pub fn report(&self) {
if let Some(info) = &self.info {
panic!(
"{}:{}:{}: error: {} '{}'",
"{}:{}:{}: error: {}",
info.source_file,
info.token.pos.line,
info.token.pos.column,
info.message,
info.token.lexeme
info.message
);
}
}

pub fn fatal(&self) {
if let Some(info) = &self.info {
eprintln!(
"{}:{}:{}: error: {} '{}'",
info.source_file,
info.token.pos.line,
info.token.pos.column,
info.message,
info.token.lexeme
);
if self.info.is_some() {
self.report();
std::process::exit(1);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ use tokenizer::Tokenizer;

fn main() {
let tokener: Rc<RefCell<Tokenizer>> = Rc::new(RefCell::new(Tokenizer::new()));
let parsr: Rc<RefCell<Parser>> = Rc::new(RefCell::new(Parser::new()));
let parsr: Rc<RefCell<Parser>> = Rc::new(RefCell::new(Parser::new(true)));
let mut symt: Symtable<Symbol> = Symtable::new();
let mut funct: FunctionInfoTable = FunctionInfoTable::new();
let mut file1: SourceFile =
SourceFile::new("/Users/rigelstar/Desktop/KagatiFoundation/bichara/examples/input1.bic");
SourceFile::new("/Users/rigelstar/Desktop/KagatiFoundation/bichara/Lib/socket/lib.bic");
let mut source_files: Vec<&mut SourceFile> = vec![&mut file1];
let ctx: Rc<RefCell<CompilerCtx>> = Rc::new(RefCell::new(CompilerCtx::new(&mut symt, &mut funct)));
let rm: RefCell<RegManager> = RefCell::new(
Expand Down
Loading

0 comments on commit b6ebb58

Please sign in to comment.