Browse Source

Merge branch 'master' of https://github.com/odin-lang/Odin

gingerBill 2 years ago
parent
commit
788f3c22bf
4 changed files with 669 additions and 42 deletions
  1. 635 23
      core/math/rand/rand.odin
  2. 1 0
      src/checker.cpp
  3. 32 18
      tests/documentation/documentation_tester.odin
  4. 1 1
      vendor/wasm/WebGL/webgl.odin

+ 635 - 23
core/math/rand/rand.odin

@@ -1,6 +1,10 @@
+/*
+Package core:math/rand implements various random number generators
+*/
 package rand
 
 import "core:intrinsics"
+import "core:mem"
 
 Rand :: struct {
 	state: u64,
@@ -12,17 +16,82 @@ Rand :: struct {
 @(private)
 global_rand := create(u64(intrinsics.read_cycle_counter()))
 
+/*
+Sets the seed used by the global random number generator.
+
+Inputs:
+- seed: The seed value
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	set_global_seed_example :: proc() {
+		rand.set_global_seed(1)
+		fmt.println(rand.uint64())
+	}
+
+Possible Output:
+
+	10
+
+*/
 set_global_seed :: proc(seed: u64) {
 	init(&global_rand, seed)
 }
 
+/*
+Creates a new random number generator.
+
+Inputs:
+- seed: The seed value to create the random number generator with
+
+Returns:
+- res: The created random number generator
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	create_example :: proc() {
+		my_rand := rand.create(1)
+		fmt.println(rand.uint64(&my_rand))
+	}
+
+Possible Output:
+
+	10
+
+*/
 @(require_results)
-create :: proc(seed: u64) -> Rand {
+create :: proc(seed: u64) -> (res: Rand) {
 	r: Rand
 	init(&r, seed)
 	return r
 }
 
+/*
+Initialises a random number generator.
+
+Inputs:
+- r: The random number generator to initialise
+- seed: The seed value to initialise this random number generator
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	init_example :: proc() {
+		my_rand: rand.Rand
+		rand.init(&my_rand, 1)
+		fmt.println(rand.uint64(&my_rand))
+	}
+
+Possible Output:
+
+	10
+
+*/
 init :: proc(r: ^Rand, seed: u64) {
 	r.state = 0
 	r.inc = (seed << 1) | 1
@@ -31,6 +100,35 @@ init :: proc(r: ^Rand, seed: u64) {
 	_random(r)
 }
 
+/*
+Initialises a random number generator to use the system random number generator.  
+The system random number generator is platform specific.  
+On `linux` refer to the `getrandom` syscall.  
+On `darwin` refer to `getentropy`.  
+On `windows` refer to `BCryptGenRandom`.
+
+All other platforms wi
+
+Inputs:
+- r: The random number generator to use the system random number generator
+
+WARNING: Panics if the system is not either `windows`, `darwin` or `linux`
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	init_as_system_example :: proc() {
+		my_rand: rand.Rand
+		rand.init_as_system(&my_rand)
+		fmt.println(rand.uint64(&my_rand))
+	}
+
+Possible Output:
+
+	10
+
+*/
 init_as_system :: proc(r: ^Rand) {
 	if !#defined(_system_random) {
 		panic(#procedure + " is not supported on this platform yet")
@@ -61,18 +159,99 @@ _random :: proc(r: ^Rand) -> u32 {
 	return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31))
 }
 
+/*
+Generates a random 32 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
+
+Inputs:
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random unsigned 32 bit value
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	uint32_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.uint32())
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.uint32(&my_rand))
+	}
+
+Possible Output:
+
+	10
+	389
+
+*/
 @(require_results)
-uint32 :: proc(r: ^Rand = nil) -> u32 { return _random(r) }
+uint32 :: proc(r: ^Rand = nil) -> (val: u32) { return _random(r) }
+
+/*
+Generates a random 64 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
+
+Inputs:
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random unsigned 64 bit value
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	uint64_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.uint64())
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.uint64(&my_rand))
+	}
+
+Possible Output:
 
+	10
+	389
+
+*/
 @(require_results)
-uint64 :: proc(r: ^Rand = nil) -> u64 {
+uint64 :: proc(r: ^Rand = nil) -> (val: u64) {
 	a := u64(_random(r))
 	b := u64(_random(r))
 	return (a<<32) | b
 }
 
+/*
+Generates a random 128 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
+
+Inputs:
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random unsigned 128 bit value
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	uint128_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.uint128())
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.uint128(&my_rand))
+	}
+
+Possible Output:
+
+	10
+	389
+
+*/
 @(require_results)
-uint128 :: proc(r: ^Rand = nil) -> u128 {
+uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
 	a := u128(_random(r))
 	b := u128(_random(r))
 	c := u128(_random(r))
@@ -80,12 +259,126 @@ uint128 :: proc(r: ^Rand = nil) -> u128 {
 	return (a<<96) | (b<<64) | (c<<32) | d
 }
 
-@(require_results) int31  :: proc(r: ^Rand = nil) -> i32  { return i32(uint32(r) << 1 >> 1) }
-@(require_results) int63  :: proc(r: ^Rand = nil) -> i64  { return i64(uint64(r) << 1 >> 1) }
-@(require_results) int127 :: proc(r: ^Rand = nil) -> i128 { return i128(uint128(r) << 1 >> 1) }
+/*
+Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.  
+The sign bit will always be set to 0, thus all generated numbers will be positive.
+
+Inputs:
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random 31 bit value
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	int31_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.int31())
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.int31(&my_rand))
+	}
+
+Possible Output:
+
+	10
+	389
+
+*/
+@(require_results) int31  :: proc(r: ^Rand = nil) -> (val: i32)  { return i32(uint32(r) << 1 >> 1) }
+/*
+Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.  
+The sign bit will always be set to 0, thus all generated numbers will be positive.
+
+Inputs:
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random 63 bit value
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	int63_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.int63())
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.int63(&my_rand))
+	}
+
+Possible Output:
 
+	10
+	389
+
+*/
+@(require_results) int63  :: proc(r: ^Rand = nil) -> (val: i64)  { return i64(uint64(r) << 1 >> 1) }
+/*
+Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.  
+The sign bit will always be set to 0, thus all generated numbers will be positive.
+
+Inputs:
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random 127 bit value
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	int127_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.int127())
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.int127(&my_rand))
+	}
+
+Possible Output:
+
+	10
+	389
+
+*/
+@(require_results) int127 :: proc(r: ^Rand = nil) -> (val: i128) { return i128(uint128(r) << 1 >> 1) }
+
+/*
+Generates a random 31 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- n: The upper bound of the generated number, this value is exclusive
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random 31 bit value in the range `(0, n]`
+
+WARNING: Panics if n is less than 0
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	int31_max_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.int31_max(16))
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.int31_max(1024, &my_rand))
+	}
+
+Possible Output:
+
+	6
+	500
+
+*/
 @(require_results)
-int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
+int31_max :: proc(n: i32, r: ^Rand = nil) -> (val: i32) {
 	if n <= 0 {
 		panic("Invalid argument to int31_max")
 	}
@@ -99,9 +392,38 @@ int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
 	}
 	return v % n
 }
+/*
+Generates a random 63 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- n: The upper bound of the generated number, this value is exclusive
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random 63 bit value in the range `(0, n]`
+
+WARNING: Panics if n is less than 0
 
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	int63_max_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.int63_max(16))
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.int63_max(1024, &my_rand))
+	}
+
+Possible Output:
+
+	6
+	500
+
+*/
 @(require_results)
-int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
+int63_max :: proc(n: i64, r: ^Rand = nil) -> (val: i64) {
 	if n <= 0 {
 		panic("Invalid argument to int63_max")
 	}
@@ -115,9 +437,38 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
 	}
 	return v % n
 }
+/*
+Generates a random 127 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- n: The upper bound of the generated number, this value is exclusive
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random 127 bit value in the range `(0, n]`
+
+WARNING: Panics if n is less than 0
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	int127_max_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.int127_max(16))
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.int127_max(1024, &my_rand))
+	}
+
+Possible Output:
 
+	6
+	500
+
+*/
 @(require_results)
-int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
+int127_max :: proc(n: i128, r: ^Rand = nil) -> (val: i128) {
 	if n <= 0 {
 		panic("Invalid argument to int127_max")
 	}
@@ -131,9 +482,38 @@ int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
 	}
 	return v % n
 }
+/*
+Generates a random integer value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- n: The upper bound of the generated number, this value is exclusive
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random integer value in the range `(0, n]`
 
+WARNING: Panics if n is less than 0
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	int_max_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.int_max(16))
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.int_max(1024, &my_rand))
+	}
+
+Possible Output:
+
+	6
+	500
+
+*/
 @(require_results)
-int_max :: proc(n: int, r: ^Rand = nil) -> int {
+int_max :: proc(n: int, r: ^Rand = nil) -> (val: int) {
 	if n <= 0 {
 		panic("Invalid argument to int_max")
 	}
@@ -144,14 +524,153 @@ int_max :: proc(n: int, r: ^Rand = nil) -> int {
 	}
 }
 
-// Uniform random distribution [0, 1)
-@(require_results) float64 :: proc(r: ^Rand = nil) -> f64 { return f64(int63_max(1<<53, r)) / (1 << 53) }
-// Uniform random distribution [0, 1)
-@(require_results) float32 :: proc(r: ^Rand = nil) -> f32 { return f32(float64(r)) }
+/*
+Generates a random double floating point value in the range `(0, 1]` using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random double floating point value in the range `(0, 1]`
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	float64_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.float64())
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.float64(&my_rand))
+	}
+
+Possible Output:
+
+	0.043
+	0.511
+
+*/
+@(require_results) float64 :: proc(r: ^Rand = nil) -> (val: f64) { return f64(int63_max(1<<53, r)) / (1 << 53) }
+
+/*
+Generates a random single floating point value in the range `(0, 1]` using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random single floating point value in the range `(0, 1]`
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	float32_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.float32())
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.float32(&my_rand))
+	}
+
+Possible Output:
+
+	0.043
+	0.511
+
+*/
+@(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(float64(r)) }
+
+/*
+Generates a random double floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- low: The lower bounds of the value, this value is inclusive
+- high: The upper bounds of the value, this value is exclusive
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random double floating point value in the range `(low, high]`
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	float64_range_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.float64_range(-10, 300))
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.float64_range(600, 900, &my_rand))
+	}
+
+Possible Output:
 
-@(require_results) float64_range :: proc(lo, hi: f64, r: ^Rand = nil) -> f64 { return (hi-lo)*float64(r) + lo }
-@(require_results) float32_range :: proc(lo, hi: f32, r: ^Rand = nil) -> f32 { return (hi-lo)*float32(r) + lo }
+	15.312
+	673.130
 
+*/
+@(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) { return (high-low)*float64(r) + low }
+/*
+Generates a random single floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- low: The lower bounds of the value, this value is inclusive
+- high: The upper bounds of the value, this value is exclusive
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- val: A random single floating point value in the range `(low, high]`
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	float32_range_example :: proc() {
+		// Using the global random number generator
+		fmt.println(rand.float32_range(-10, 300))
+		// Using local random number generator
+		my_rand := rand.create(1)
+		fmt.println(rand.float32_range(600, 900, &my_rand))
+	}
+
+Possible Output:
+
+	15.312
+	673.130
+
+*/
+@(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) { return (high-low)*float32(r) + low }
+
+/*
+Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- p: The byte slice to fill
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- n: The number of bytes generated
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	read_example :: proc() {
+		// Using the global random number generator
+		data: [8]byte
+		n := rand.read(data[:])
+		fmt.println(n)
+		fmt.println(data)
+	}
+
+Possible Output:
+
+	8
+	[32, 4, 59, 7, 1, 2, 2, 119]
+
+*/
 @(require_results)
 read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
 	pos := i8(0)
@@ -168,19 +687,81 @@ read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
 	return
 }
 
-// perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n)
+/*
+Creates a slice of `int` filled with random values using the provided random number generator. If no generator is provided the global random number generator will be used.  
+
+*Allocates Using Provided Allocator*
+
+Inputs:
+- n: The size of the created slice
+- r: The random number generator to use, or nil for the global generator
+- allocator: (default: context.allocator)
+
+Returns:
+- res: A slice filled with random values
+- err: An allocator error if one occured, `nil` otherwise
+
+Example:
+	import "core:math/rand"
+	import "core:mem"
+	import "core:fmt"
+
+	perm_example :: proc() -> (err: mem.Allocator_Error) {
+		// Using the global random number generator and using the context allocator
+		data := rand.perm(4) or_return
+		fmt.println(data)
+		defer delete(data, context.allocator)
+
+		// Using local random number generator and temp allocator
+		my_rand := rand.create(1)
+		data_tmp := rand.perm(4, &my_rand, context.temp_allocator) or_return
+		fmt.println(data_tmp)
+
+		return
+	}
+
+Possible Output:
+
+	[7201011, 3, 9123, 231131]
+	[19578, 910081, 131, 7]
+
+*/
 @(require_results)
-perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> []int {
-	m := make([]int, n, allocator)
+perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
+	m := make([]int, n, allocator) or_return
 	for i := 0; i < n; i += 1 {
 		j := int_max(i+1, r)
 		m[i] = m[j]
 		m[j] = i
 	}
-	return m
+	return m, {}
 }
 
+/*
+Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- array: The slice to randomize
+- r: The random number generator to use, or nil for the global generator
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	shuffle_example :: proc() {
+		// Using the global random number generator
+		data: [4]int = { 1, 2, 3, 4 }
+		fmt.println(data) // the contents are in order
+		rand.shuffle(data[:])
+		fmt.println(data) // the contents have been shuffled
+	}
+
+Possible Output:
 
+	[1, 2, 3, 4]
+	[2, 4, 3, 1]
+
+*/
 shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
 	n := i64(len(array))
 	if n < 2 {
@@ -193,7 +774,38 @@ shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
 	}
 }
 
-// Returns a random element from the given slice
+/*
+Returns a random element from the provided slice. If no generator is provided the global random number generator will be used.  
+
+Inputs:
+- array: The slice to choose an element from
+- r: The random number generator to use, or nil for the global generator
+
+Returns:
+- res: A random element from `array`
+
+Example:
+	import "core:math/rand"
+	import "core:fmt"
+
+	choice_example :: proc() {
+		// Using the global random number generator
+		data: [4]int = { 1, 2, 3, 4 }
+		fmt.println(rand.choice(data[:]))
+		fmt.println(rand.choice(data[:]))
+		fmt.println(rand.choice(data[:]))
+		fmt.println(rand.choice(data[:]))
+	}
+
+
+Possible Output:
+
+	3
+	2
+	2
+	4
+
+*/
 @(require_results)
 choice :: proc(array: $T/[]$E, r: ^Rand = nil) -> (res: E) {
 	n := i64(len(array))
@@ -201,4 +813,4 @@ choice :: proc(array: $T/[]$E, r: ^Rand = nil) -> (res: E) {
 		return E{}
 	}
 	return array[int63_max(n, r)]
-}
+}

+ 1 - 0
src/checker.cpp

@@ -3524,6 +3524,7 @@ gb_internal void check_decl_attributes(CheckerContext *c, Array<Ast *> const &at
 			if (!proc(c, elem, name, value, ac)) {
 				if (!build_context.ignore_unknown_attributes) {
 					error(elem, "Unknown attribute element name '%.*s'", LIT(name));
+					error_line("\tDid you forget to use build flag '-ignore-unknown-attributes'?\n");
 				}
 			}
 		}

+ 32 - 18
tests/documentation/documentation_tester.odin

@@ -14,6 +14,7 @@ Example_Test :: struct {
 	package_name: string,
 	example_code: []string,
 	expected_output: []string,
+	skip_output_check: bool,
 }
 
 g_header:   ^doc.Header
@@ -145,6 +146,7 @@ find_and_add_examples :: proc(docs: string, package_name: string, entity_name: s
 	curr_block_kind := Block_Kind.Other
 	start := 0
 
+	found_possible_output: bool
 	example_block: Block // when set the kind should be Example
 	output_block: Block // when set the kind should be Output
 	// rely on zii that the kinds have not been set
@@ -178,10 +180,16 @@ find_and_add_examples :: proc(docs: string, package_name: string, entity_name: s
 			switch {
 			case strings.has_prefix(line, "Example:"): next_block_kind = .Example
 			case strings.has_prefix(line, "Output:"): next_block_kind = .Output
+			case strings.has_prefix(line, "Possible Output:"):
+				next_block_kind = .Output
+				found_possible_output = true
 			}
 		case .Example:
 			switch {
 			case strings.has_prefix(line, "Output:"): next_block_kind = .Output
+			case strings.has_prefix(line, "Possible Output:"):
+				next_block_kind = .Output
+				found_possible_output = true
 			case ! (text == "" || strings.has_prefix(line, "\t")): next_block_kind = .Other
 			}
 		case .Output:
@@ -219,8 +227,9 @@ find_and_add_examples :: proc(docs: string, package_name: string, entity_name: s
 		{
 			// Output block starts with
 			// `Output:` and a number of white spaces,
+			// `Possible Output:` and a number of white spaces,
 			lines := &output_block.lines
-			for len(lines) > 0 && (strings.trim_space(lines[0]) == "" || strings.has_prefix(lines[0], "Output:")) {
+			for len(lines) > 0 && (strings.trim_space(lines[0]) == "" || strings.has_prefix(lines[0], "Output:") || strings.has_prefix(lines[0], "Possible Output:")) {
 				lines^ = lines[1:]
 			}
 			// Additionally we need to strip all empty lines at the end of output to not include those in the expected output
@@ -240,6 +249,7 @@ find_and_add_examples :: proc(docs: string, package_name: string, entity_name: s
 			package_name = package_name,
 			example_code = example_block.lines,
 			expected_output = output_block.lines,
+			skip_output_check = found_possible_output,
 		})
 	}
 }
@@ -404,25 +414,29 @@ main :: proc() {
 			continue
 		}
 
-		fmt.sbprintf(&test_runner, "\t%v_%v()\n", test.package_name, code_test_name)
-		fmt.sbprintf(&test_runner, "\t_check(%q, `", code_test_name)
-		had_line_error: bool
-		for line in test.expected_output {
-			// NOTE: this will escape the multiline string. Even with a backslash it still escapes due to the semantics of `
-			// I don't think any examples would really need this specific character so let's just make it forbidden and change
-			// in the future if we really need to
-			if strings.contains_rune(line, '`') {
-				fmt.eprintf("The line %q in the output for \"%s.%s\" contains a ` which is not allowed\n", line, test.package_name, test.entity_name)
-				g_bad_doc = true
-				had_line_error = true
+		// NOTE: packages like 'rand' are random by nature, in these cases we cannot verify against the output string
+		// in these cases we just mark the output as 'Possible Output' and we simply skip checking against the output
+		if ! test.skip_output_check {
+			fmt.sbprintf(&test_runner, "\t%v_%v()\n", test.package_name, code_test_name)
+			fmt.sbprintf(&test_runner, "\t_check(%q, `", code_test_name)
+			had_line_error: bool
+			for line in test.expected_output {
+				// NOTE: this will escape the multiline string. Even with a backslash it still escapes due to the semantics of `
+				// I don't think any examples would really need this specific character so let's just make it forbidden and change
+				// in the future if we really need to
+				if strings.contains_rune(line, '`') {
+					fmt.eprintf("The line %q in the output for \"%s.%s\" contains a ` which is not allowed\n", line, test.package_name, test.entity_name)
+					g_bad_doc = true
+					had_line_error = true
+				}
+				strings.write_string(&test_runner, line)
+				strings.write_string(&test_runner, "\n")
 			}
-			strings.write_string(&test_runner, line)
-			strings.write_string(&test_runner, "\n")
-		}
-		if had_line_error {
-			continue
+			if had_line_error {
+				continue
+			}
+			strings.write_string(&test_runner, "`)\n")
 		}
-		strings.write_string(&test_runner, "`)\n")
 		save_path := fmt.tprintf("verify/test_%v_%v.odin", test.package_name, code_test_name)
 
 		test_file_handle, err := os.open(save_path, os.O_WRONLY | os.O_CREATE); if err != 0 {

+ 1 - 1
vendor/wasm/WebGL/webgl.odin

@@ -50,7 +50,7 @@ foreign webgl {
 	AttachShader       :: proc(program: Program, shader: Shader) ---
 	BindAttribLocation :: proc(program: Program, index: i32, name: string) ---
 	BindBuffer         :: proc(target: Enum, buffer: Buffer) ---
-	BindFramebuffer    :: proc(target: Enum, buffer: Buffer) ---
+	BindFramebuffer    :: proc(target: Enum, framebuffer: Framebuffer) ---
 	BindTexture        :: proc(target: Enum, texture: Texture) ---
 	BlendColor         :: proc(red, green, blue, alpha: f32) ---
 	BlendEquation      :: proc(mode: Enum) ---