Skip to content

Commit

Permalink
feat: user input
Browse files Browse the repository at this point in the history
  • Loading branch information
araujo88 committed Jan 25, 2025
1 parent e2b6bf0 commit 28b22e9
Show file tree
Hide file tree
Showing 13 changed files with 691 additions and 56 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ jobs:
- name: Build Brainrot
run: |
bison -d -Wcounterexamples lang.y -o lang.tab.c
flex lang.l
gcc -o brainrot lib/hm.c lib/mem.c lang.tab.c lex.yy.c ast.c -lfl -lm
make
- name: Upload build artifacts
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -75,7 +73,7 @@ jobs:
run: |
for f in test_cases/*.brainrot; do
echo "Running Valgrind on $f..."
valgrind --leak-check=full --error-exitcode=1 ./brainrot < "$f"
valgrind --leak-check=full --error-exitcode=1 ./brainrot "$f"
echo
done
working-directory: .
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ LDFLAGS := -lfl -lm

# Source files and directories
SRC_DIR := lib
SRCS := $(SRC_DIR)/hm.c $(SRC_DIR)/mem.c ast.c
SRCS := $(SRC_DIR)/hm.c $(SRC_DIR)/mem.c $(SRC_DIR)/input.c ast.c
GENERATED_SRCS := lang.tab.c lex.yy.c
ALL_SRCS := $(SRCS) $(GENERATED_SRCS)

Expand Down Expand Up @@ -56,7 +56,7 @@ clean:
valgrind:
@for f in test_cases/*.brainrot; do \
echo "Ayo, Valgrind is pulling up on $$f..."; \
valgrind --leak-check=full --error-exitcode=1 ./$(TARGET) < $$f; \
valgrind --leak-check=full --error-exitcode=1 ./$(TARGET) $$f; \
if [ $$? -eq 0 ]; then echo "Valgrind passed for $$f, no memory leaks. Big W!"; \
else echo "Valgrind found a memory leak in $$f, taking an L. Better grind harder."; exit 1; fi; \
echo; \
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ make
2. Run your Brainrot program:

```bash
./brainrot < hello.brainrot
./brainrot hello.brainrot
```

Check out the [examples](examples/README.md):
Expand All @@ -113,8 +113,9 @@ Check out the [examples](examples/README.md):
## 🗪 Community

Join our community on:
- [Discord](https://discord.gg/FjHhvBHSGj)
- [Reddit](https://www.reddit.com/r/Brainrotlang/)

- [Discord](https://discord.gg/FjHhvBHSGj)
- [Reddit](https://www.reddit.com/r/Brainrotlang/)

## 📚 Language Reference

Expand Down
85 changes: 73 additions & 12 deletions ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ extern void chill(unsigned int seconds);
extern void yapping(const char *format, ...);
extern void yappin(const char *format, ...);
extern void baka(const char *format, ...);
extern char slorp_char(char chr);
extern char *slorp_string(char *string);
extern int slorp_int(int val);
extern short slorp_short(short val);
extern float slorp_float(float var);
extern double slorp_double(double var);
extern TypeModifiers get_variable_modifiers(const char *name);
extern int yylineno;

Expand Down Expand Up @@ -264,7 +270,6 @@ ASTNode *create_int_node(int value)
return node;
}


ASTNode *create_array_declaration_node(char *name, int length, VarType var_type)
{
ASTNode *node = SAFE_MALLOC(ASTNode);
Expand Down Expand Up @@ -642,7 +647,6 @@ void *handle_binary_operation(ASTNode *node, int result_type)
*(short *)right_value = evaluate_expression_short(node->data.op.right);
break;


default:
yyerror("Unsupported type promotion");
return NULL;
Expand Down Expand Up @@ -1073,7 +1077,6 @@ void *handle_unary_expression(ASTNode *node, void *operand_value, int operand_ty
}
}


float evaluate_expression_float(ASTNode *node)
{
if (!node)
Expand Down Expand Up @@ -1268,7 +1271,6 @@ double evaluate_expression_double(ASTNode *node)
return result;
}
return 0.0L;

}
default:
yyerror("Invalid double expression");
Expand Down Expand Up @@ -1613,7 +1615,7 @@ int evaluate_expression_int(ASTNode *node)
}
case NODE_FUNC_CALL:
{
int *res = (int *)handle_function_call(node);
int *res = (int *)handle_function_call(node);
if (res != NULL)
{
int return_val = *res;
Expand All @@ -1628,12 +1630,12 @@ int evaluate_expression_int(ASTNode *node)
}
}

void *handle_function_call(ASTNode* node)
void *handle_function_call(ASTNode *node)
{
execute_function_call(
node->data.func_call.function_name,
node->data.func_call.arguments);
void* return_value = NULL;
void *return_value = NULL;
if (current_return_value.has_value)
{
switch (current_return_value.type)
Expand Down Expand Up @@ -1669,7 +1671,6 @@ void *handle_function_call(ASTNode* node)
return return_value;
}


bool evaluate_expression_bool(ASTNode *node)
{
if (!node)
Expand Down Expand Up @@ -1935,7 +1936,7 @@ bool is_short_expression(ASTNode *node)
}
}

Function* get_function(const char *name)
Function *get_function(const char *name)
{
Function *func = function_table;
while (func != NULL)
Expand Down Expand Up @@ -2335,6 +2336,10 @@ void execute_statement(ASTNode *node)
{
execute_chill_call(node->data.func_call.arguments);
}
else if (strcmp(node->data.func_call.function_name, "slorp") == 0)
{
execute_slorp_call(node->data.func_call.arguments);
}
break;
case NODE_FOR_STATEMENT:
execute_for_statement(node);
Expand Down Expand Up @@ -2420,7 +2425,6 @@ void execute_statement(ASTNode *node)
}
}


void execute_statements(ASTNode *node)
{
if (!node)
Expand Down Expand Up @@ -2956,6 +2960,64 @@ void execute_chill_call(ArgumentList *args)
chill(formatNode->data.ivalue);
}

void execute_slorp_call(ArgumentList *args)
{
if (!args || args->expr->type != NODE_IDENTIFIER)
{
yyerror("slurp requires a variable identifier");
return;
}

char *name = args->expr->data.name;
Variable *var = get_variable(name);
if (!var)
{
yyerror("Undefined variable");
return;
}

switch (var->var_type)
{
case VAR_INT:
{
int val = 0;
val = slorp_int(val);
set_int_variable(name, val, var->modifiers);
break;
}
case VAR_FLOAT:
{
float val = 0.0f;
val = slorp_float(val);
set_float_variable(name, val, var->modifiers);
break;
}
case VAR_DOUBLE:
{
double val = 0.0;
val = slorp_double(val);
set_double_variable(name, val, var->modifiers);
break;
}
case VAR_SHORT:
{
short val = 0;
val = slorp_short(val);
set_short_variable(name, val, var->modifiers);
break;
}
case VAR_CHAR:
{
char val = 0;
val = slorp_char(val);
set_int_variable(name, val, var->modifiers);
break;
}
default:
yyerror("Unsupported type for slorp");
}
}

void bruh()
{
LONGJMP();
Expand Down Expand Up @@ -3573,7 +3635,7 @@ void handle_return_statement(ASTNode *expr)
}
}
// skibidi main function do not have jump buffer
if(CURRENT_JUMP_BUFFER() != NULL)
if (CURRENT_JUMP_BUFFER() != NULL)
LONGJMP();
}

Expand Down Expand Up @@ -3644,4 +3706,3 @@ void free_function_table(void)
}
function_table = NULL;
}

5 changes: 3 additions & 2 deletions ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ void enter_scope();
void free_scope(Scope *scope);
void add_variable_to_scope(const char *name, Variable *var);
Variable *variable_new(char *name);
Function* get_function(const char *name);
Function *get_function(const char *name);
VarType get_function_return_type(const char *name);

/* Node creation functions */
Expand Down Expand Up @@ -366,14 +366,15 @@ void execute_yappin_call(ArgumentList *args);
void execute_baka_call(ArgumentList *args);
void execute_ragequit_call(ArgumentList *args);
void execute_chill_call(ArgumentList *args);
void execute_slorp_call(ArgumentList *args);
void free_ast(ASTNode *node);
void reset_modifiers(void);
bool check_and_mark_identifier(ASTNode *node, const char *contextErrorMessage);
void bruh();
size_t count_expression_list(ExpressionList *list);
size_t handle_sizeof(ASTNode *node);
size_t get_type_size(char *name);
void *handle_function_call(ASTNode* node);
void *handle_function_call(ASTNode *node);

/* User-defined functions */
Function *create_function(char *name, VarType return_type, Parameter *params, ASTNode *body);
Expand Down
41 changes: 28 additions & 13 deletions docs/brainrot-user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ count = 42;
A **statement** often ends with a **semicolon** `;` unless it is a compound statement (like `{ ... }`).

### Increment and Decrement Operators (`++`, `--`)

In addition to basic arithmetic and logical expressions, you can also use **increment** (`++`) and **decrement** (`--`) operators in Brainrot.

- **Pre-Increment (`++i`)**: Increments the value of `i` by 1 before it is used in an expression.
Expand All @@ -79,7 +80,6 @@ In addition to basic arithmetic and logical expressions, you can also use **incr

You can use these operators in expressions to simplify code and make it more concise.


Examples of valid statements:

```c
Expand Down Expand Up @@ -135,6 +135,7 @@ flex (rizz j = 0; j < 3; j = j + 1) {
yapping("j = %d", j);
}
```

- **`init_expr`**: A declaration or expression to initialize loop variables (e.g., `rizz j = 0`).
- **`condition`**: Checked each iteration (e.g., `j < 3`).
- **`increment`**: Executed at the end of each iteration (e.g., `j = j + 1`).
Expand Down Expand Up @@ -201,6 +202,8 @@ Brainrot includes some built-in functions for convenience:
| **yappin** | `stdout` | No | Precise control over spacing/newlines |
| **baka** | `stderr` | No | Log errors or warnings, typically no extra newline |
| **ragequit** | - | - | Terminates program execution immediately with the provided exit code. |
| **chill** | - | - | Sleeps for an integer number of seconds. |
| **slorp** | `stdin` | - | Reads user input. |

## 9.1. yapping

Expand Down Expand Up @@ -320,6 +323,30 @@ skibidi main {
}
```

## 9.6. slorp

**Prototype**

```c
void slorp(var_type var_name);
```
**Key Points**
- Reads user input (similar to C's `scanf` but safer)
### Example
```c
skibidi main {
rizz num;
yapping("Enter a number:");
slorp(num);
yapping("You typed: %d", num);
bussin 0;
}
```

---

# 10. Example Program
Expand Down Expand Up @@ -376,15 +403,3 @@ skibidi main {
- **Syntax** is otherwise quite C-like: `;` to end statements, braces `{ }` to define blocks, parentheses `( )` around conditions.
- **Expressions** accept typical operators (`+`,`++`, `-`,`--`, `*`, `/`, `%`, relational, logical) plus the assignment operator `=`, matching standard precedence rules.
- **Escapes in strings** (`"\n"`, `"\t"`, etc.) may require an unescape function in your lexer, so check that it’s converting them into real newlines or tabs at runtime.

---

# Final Thoughts

This language—often called **Brainrot**—provides a playful wrapper around standard C-like structures, with unique keywords and easy built-in printing:

- **`yapping`** for automatic line-based output.
- **`yappin`** for precise printing without automatic newlines.
- **`baka`** for error messages or logs to `stderr`.

Use them together with the custom control-flow keywords (`goon`, `flex`, etc.) and custom variable type (`rizz`) to write concise, whimsical, yet powerful scripts. Enjoy experimenting with your new language!
Loading

0 comments on commit 28b22e9

Please sign in to comment.