Skip to content

Commit

Permalink
prelude_uint.mk: Add, with unsigned integer comparison functions
Browse files Browse the repository at this point in the history
  • Loading branch information
LukeShu committed Sep 5, 2019
1 parent 5311af3 commit d0b3ed4
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 0 deletions.
10 changes: 10 additions & 0 deletions prelude.mk
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
# - Variable: SPACE
# - Function: str.eq
#
# Unsigned integer support:
# - Function: uint.max
# - Function: uint.min
# - Function: uint.eq
# - Function: uint.ge
# - Function: uint.le
# - Function: uint.gt
# - Function: uint.lt
#
# Path support:
# - Function: path.trimprefix
# - Function: path.addprefix
Expand Down Expand Up @@ -61,6 +70,7 @@ _prelude.mk := $(lastword $(MAKEFILE_LIST))
# matter. Anything eager must go in this main `prelude.mk` file.
include $(dir $(_prelude.mk))prelude_bool.mk
include $(dir $(_prelude.mk))prelude_str.mk
include $(dir $(_prelude.mk))prelude_uint.mk
include $(dir $(_prelude.mk))prelude_path.mk
include $(dir $(_prelude.mk))prelude_go.mk

Expand Down
81 changes: 81 additions & 0 deletions prelude_uint.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# This is part of `prelude.mk`, split out for organizational purposes.
# !!! NOTHING EAGER IS ALLOWED TO HAPPEN IN THIS FILE !!!

#
# Unsigned integer support

_uint.is-uint-or-empty = $(if $1,$(call _uint.is-uint,$1),$(TRUE))
_uint.is-uint = $(and $(call str.eq,$(words $1),1),$(filter 0% 1% 2% 3% 4% 5% 6% 7% 8% 9%,$1),$(call _uint.is-uint-or-empty,$(strip \
$(patsubst 0%,%,\
$(patsubst 1%,%,\
$(patsubst 2%,%,\
$(patsubst 3%,%,\
$(patsubst 4%,%,\
$(patsubst 5%,%,\
$(patsubst 6%,%,\
$(patsubst 7%,%,\
$(patsubst 8%,%,\
$(patsubst 9%,%,\
$1)))))))))))))

# Usage: $(call _uint.normalize,UINT)
# Example: $(call _uint.normalize,0) => 0
# Example: $(call _uint.normalize,004) => 4
#
# Normalizes a decimal-uint-string. Right now, that just means
# that it $(strip)s it, and trims leading 0s.
_uint.normalize = $(strip \
$(if $(call _uint.is-uint,$1),,$(error argument to uint.* function is not a uint: '$1'))\
$(if $(filter 0%,$(filter-out 0,$1)),\
$(call _uint.normalize,$(patsubst 0%,%,$1)),\
$1))

# Usage: $(call uint.max,UINT,UINT)
# Example: $(call uint.max,3,2) => 3
uint.max = $(call _uintx.to.uint,$(call _uintx.max,$(call _uintx.from.uint,$1),$(call _uintx.from.uint,$2)))

# Usage: $(call uint.min,UINT,UINT)
# Example: $(call uint.min,3,2) => 2
uint.min = $(call _uintx.to.uint,$(call _uintx.min,$(call _uintx.from.uint,$1),$(call _uintx.from.uint,$2)))

# Usage: $(call _uint.eq,UINT,UINT)
uint.eq = $(call str.eq,$(call _uint.normalize,$1),$(call _uint.normalize,$2))

# These opperate entirely in terms of functions that call
# _uint.normalize, so they don't need to.
uint.ge = $(call uint.eq,$(call uint.max,$1,$2),$1)
uint.le = $(call uint.eq,$(call uint.min,$1,$2),$1)
uint.gt = $(and $(call uint.ge,$1,$2),$(call not,$(call uint.eq,$1,$2)))
uint.lt = $(and $(call uint.le,$1,$2),$(call not,$(call uint.eq,$1,$2)))

#
# "uintx" support: Unsigned integers represented as a list of "x"s
#
# Several operations are easier with this representation than with a
# decimal-string representation.

# Usage: $(call _uintx.to.uint,UINTX)
# Example: $(call _uintx.to.uint,x x x x) => 4
_uintx.to.uint = $(words $1)

# Usage: $(call _uintx.from.uint.helper,UINT,PARTIALL_UINTX)
# Example: $(call _uintx.from.uint.helper,3,) =>
# $(call _uintx.from.uint.helper,3,x) =>
# $(call _uintx.from.uint.helper,3,x x) =>
# $(call _uintx.from.uint.helper,3,x x x) =>
# x x x
_uintx.from.uint.helper = $(if $(call str.eq,$1,$(call _uintx.to.uint,$2)), \
$2, \
$(call _uintx.from.uint.helper,$1,$2 x))

# Usage: $(call _uintx.from.uint,UINT)
# Example: $(call _uintx.from.uint,4) => x x x x
_uintx.from.uint = $(foreach x,$(call _uintx.from.uint.helper,$(call _uint.normalize,$1),),x)

# Usage: $(call _uintx.max,UINTX,UINTX)
# Example: $(call _uintx.max,x x x,x x) => x x x
_uintx.max = $(subst xx,x,$(join $1,$2))

# Usage: $(call _uintx.min,UINTX,UINTX)
# Example: $(call _uintx.min,x x x,x x) => x x
_uintx.min = $(subst xx,x,$(filter xx,$(join $1,$2)))
81 changes: 81 additions & 0 deletions tests/prelude_uint.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bats

load common

# These tests are ordered such that it makes sense to debug them from
# top to bottom.

@test "prelude_uint.mk: _uint.normalize" {
check_expr_eq strict '$(call _uint.normalize,4)' '4'
check_expr_eq strict '$(call _uint.normalize,0)' '0'
check_expr_eq strict '$(call _uint.normalize,004)' '4'
check_expr_eq strict '$(call _uint.normalize, 4)' '4'
check_expr_eq strict '$(call _uint.normalize,4 )' '4'
# check that it errors for things that aren't uint
not make EXPR='$(call _uint.normalize,)' expr-eq-strict-actual
not make EXPR='$(call _uint.normalize, )' expr-eq-strict-actual
not make EXPR='$(call _uint.normalize,a)' expr-eq-strict-actual
not make EXPR='$(call _uint.normalize,9a)' expr-eq-strict-actual
not make EXPR='$(call _uint.normalize,a9)' expr-eq-strict-actual
not make EXPR='$(call _uint.normalize,-4)' expr-eq-strict-actual
not make EXPR='$(call _uint.normalize,4.2)' expr-eq-strict-actual
}

@test "prelude_uint.mk: _uintx.to.uint" {
check_expr_eq strict '$(call _uintx.to.uint,x x x x)' '4'
}

@test "prelude_uint.mk: _uintx.from.uint.helper" {
check_expr_eq echo '$(call _uintx.from.uint.helper,3,)' 'x x x'
}

@test "prelude_uint.mk: _uintx.from.uint" {
check_expr_eq strict '$(call _uintx.from.uint,4)' 'x x x x'
}

@test "prelude_uint.mk: _uintx.max" {
check_expr_eq strict '$(call _uintx.max,x x x,x x)' 'x x x'
}

@test "prelude_uint.mk: _uintx.min" {
check_expr_eq strict '$(call _uintx.min,x x x,x x)' 'x x'
}

@test "prelude_uint.mk: uint.max" {
check_expr_eq strict '$(call uint.max,3,2)' '3'
}

@test "prelude_uint.mk: uint.min" {
check_expr_eq strict '$(call uint.min,3,2)' '2'
}

@test "prelude_uint.mk: uint.eq" {
check_expr_eq strict '$(if $(call uint.eq,3,3),true,false)' 'true'
check_expr_eq strict '$(if $(call uint.eq,3,4),true,false)' 'false'
check_expr_eq strict '$(if $(call uint.eq,3,03),true,false)' 'true'
check_expr_eq strict '$(if $(call uint.eq, 3 , 03),true,false)' 'true'
}

@test "prelude_uint.mk: uint.ge" {
check_expr_eq strict '$(if $(call uint.ge,2,3),true,false)' 'false'
check_expr_eq strict '$(if $(call uint.ge,3,3),true,false)' 'true'
check_expr_eq strict '$(if $(call uint.ge,4,3),true,false)' 'true'
}

@test "prelude_uint.mk: uint.le" {
check_expr_eq strict '$(if $(call uint.le,2,3),true,false)' 'true'
check_expr_eq strict '$(if $(call uint.le,3,3),true,false)' 'true'
check_expr_eq strict '$(if $(call uint.le,4,3),true,false)' 'false'
}

@test "prelude_uint.mk: uint.gt" {
check_expr_eq strict '$(if $(call uint.gt,2,3),true,false)' 'false'
check_expr_eq strict '$(if $(call uint.gt,3,3),true,false)' 'false'
check_expr_eq strict '$(if $(call uint.gt,4,3),true,false)' 'true'
}

@test "prelude_uint.mk: uint.lt" {
check_expr_eq strict '$(if $(call uint.lt,2,3),true,false)' 'true'
check_expr_eq strict '$(if $(call uint.lt,3,3),true,false)' 'false'
check_expr_eq strict '$(if $(call uint.lt,4,3),true,false)' 'false'
}

0 comments on commit d0b3ed4

Please sign in to comment.