Skip to content

Commit

Permalink
Merge pull request #244 from KennyOliver/issue-243
Browse files Browse the repository at this point in the history
Issue 243: Built-in `random` function always gives same value on every call
  • Loading branch information
KennyOliver authored Jan 19, 2025
2 parents 963ffe2 + 10b1547 commit b262e41
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 36 deletions.
48 changes: 15 additions & 33 deletions src/interpreter/builtins.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
#include "builtins.h"
#include "../interpreter/interpreter.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#ifdef __unix__
#include <dlfcn.h>
#endif
#include <dlfcn.h>

// Helper function to check if a LiteralType matches an ArgType
bool literal_type_matches_arg_type(LiteralType lit_type, ArgType arg_type) {
Expand Down Expand Up @@ -230,8 +215,8 @@ InterpretResult builtin_random(ASTNode *node, Environment *env) {
FLOAT_SIZE min = 0.0L; // default min
FLOAT_SIZE max = 1.0L; // default max

// Determine how many arguments were passed
ASTNode *arg_node = node->function_call.arguments;

size_t num_args = 0;
ASTNode *temp = arg_node;
while (temp) {
Expand All @@ -243,48 +228,46 @@ InterpretResult builtin_random(ASTNode *node, Environment *env) {
"(integer or float), but %zu provided.\n",
num_args);
}

if (num_args == 1) {
// One argument provided: set max, min remains 0.0
ArgumentSpec specs[1];
specs[0].type = ARG_TYPE_NUMERIC;
specs[0].out_ptr = &max;

InterpretResult args_res = interpret_arguments(arg_node, env, 1, specs);
if (args_res.is_error) {
return args_res;
}
} else if (num_args == 2) {
// Two arguments provided: set min and max
ArgumentSpec specs[2];
specs[0].type = ARG_TYPE_NUMERIC;
specs[0].out_ptr = &min;
specs[1].type = ARG_TYPE_NUMERIC;
specs[1].out_ptr = &max;

InterpretResult args_res = interpret_arguments(arg_node, env, 2, specs);
if (args_res.is_error) {
return args_res;
}
}

// Seed the random number generator once
static bool seeded = false;
if (!seeded) {
srand((unsigned int)(time(NULL) ^ getpid()));
seeded = true;
}

// Swap min & max if min > max to ensure correct range
if (min > max) {
FLOAT_SIZE temp_val = min;
min = max;
max = temp_val;
}

// Generate random number
FLOAT_SIZE random_number =
min + ((FLOAT_SIZE)rand() / (FLOAT_SIZE)RAND_MAX) * (max - min);
static bool seeded = false;
if (!seeded) {
#ifdef _WIN32
srand((unsigned int)(time(NULL) ^ GetTickCount()));
#else
struct timeval tv;
gettimeofday(&tv, NULL);
srand((unsigned int)(tv.tv_sec ^ tv.tv_usec ^ getpid()));
#endif
seeded = true;
}

FLOAT_SIZE random_fraction = ((FLOAT_SIZE)rand() / (FLOAT_SIZE)RAND_MAX);
FLOAT_SIZE random_number = min + random_fraction * (max - min);

debug_print_int("Random number generated (min: " FLOAT_FORMAT
", max: " FLOAT_FORMAT "): `" FLOAT_FORMAT "`\n",
Expand All @@ -293,7 +276,6 @@ InterpretResult builtin_random(ASTNode *node, Environment *env) {
LiteralValue result;
result.type = TYPE_FLOAT;
result.data.floating_point = random_number;

return make_result(result, false, false);
}

Expand Down
14 changes: 14 additions & 0 deletions src/interpreter/builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@
#define BUILTINS_H

#include "../debug/debug.h"
#include "../interpreter/interpreter.h"
#include "../shared/ast_types.h"
#include "interpreter_types.h"
#include "utils.h"
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#ifdef __unix__
#include <dlfcn.h>
#endif
#include <dlfcn.h>
#ifndef _WIN32
#include <sys/time.h>
#endif

typedef enum {
ARG_TYPE_INTEGER,
Expand Down
2 changes: 1 addition & 1 deletion vscode-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "flavorlang-vscode",
"displayName": "FlavorLang Support",
"description": "Syntax highlighting for FlavorLang programming language.",
"version": "1.5.0",
"version": "1.6.0",
"publisher": "KennyOliver",
"repository": {
"type": "git",
Expand Down
13 changes: 11 additions & 2 deletions vscode-extension/syntaxes/flavorlang.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
{ "include": "#comments" },
{ "include": "#strings" },
{ "include": "#keywords" },
{ "include": "#builtin-functions" },
{ "include": "#functions" },
{ "include": "#numbers" },
{ "include": "#operators" },
Expand Down Expand Up @@ -40,14 +41,22 @@
"patterns": [
{
"name": "keyword.control.flavorlang",
"match": "\\b(let|const|if|elif|else|for|in|while|create|burn|deliver|check|is|rescue|try|rescue|finish|break|continue|import|export|cimport|floor|ceil|round|abs)\\b"
"match": "\\b(let|const|if|elif|else|for|in|while|create|burn|deliver|check|is|rescue|try|finish|break|continue)\\b"
},
{
"name": "keyword.other.flavorlang",
"match": "\\b(True|False|None)\\b"
}
]
},
"builtin-functions": {
"patterns": [
{
"name": "support.function.builtin.flavorlang",
"match": "\\b(?:sample|serve|burn|random|floor|ceil|round|abs|get_time|taste_file|plate_file|garnish_file|length|sleep|cimport)\\b(?=\\()"
}
]
},
"functions": {
"patterns": [
{
Expand All @@ -56,7 +65,7 @@
},
{
"name": "entity.name.function.call.flavorlang",
"match": "\\b[a-zA-Z_][a-zA-Z0-9_]*\\b(?=\\()"
"match": "\\b(?!sample\\b|serve\\b|burn\\b|random\\b|floor\\b|ceil\\b|round\\b|abs\\b|get_time\\b|taste_file\\b|plate_file\\b|garnish_file\\b|length\\b|sleep\\b|cimport\\b)[a-zA-Z_][a-zA-Z0-9_]*\\b(?=\\()"
}
]
},
Expand Down

0 comments on commit b262e41

Please sign in to comment.