github.com/nevalang/neva@v0.23.1-0.20240507185603-7696a9bb8dda/internal/compiler/analyzer/semver.go (about) 1 package analyzer 2 3 import ( 4 "fmt" 5 6 "github.com/Masterminds/semver/v3" 7 8 "github.com/nevalang/neva/internal/compiler" 9 src "github.com/nevalang/neva/internal/compiler/sourcecode" 10 ) 11 12 // semverCheck ensures that module is compatible with existing compiler 13 // by checking it's version against semver. It uses minor as major. 14 func (a Analyzer) semverCheck(mod src.Module, modRef src.ModuleRef) *compiler.Error { 15 moduleVersion, semverErr := semver.NewVersion(mod.Manifest.LanguageVersion) 16 if semverErr != nil { 17 return &compiler.Error{ 18 Err: fmt.Errorf("%w: %v", ErrCompilerVersion, semverErr), 19 } 20 } 21 22 compilerVersion, semverErr := semver.NewVersion(a.compilerVersion) 23 if semverErr != nil { 24 return &compiler.Error{ 25 Err: fmt.Errorf("%w: %v", ErrCompilerVersion, semverErr), 26 } 27 } 28 29 // major versions should be strictly equal 30 // if got major more than ours, then compatibility in that program is broken 31 // and vice versa if got major less than ours 32 if moduleVersion.Major() != compilerVersion.Major() { 33 return &compiler.Error{ 34 Err: fmt.Errorf( 35 "%w: different majors: module %v wants %v while current is %v", 36 ErrCompilerVersion, 37 modRef, mod.Manifest.LanguageVersion, a.compilerVersion, 38 ), 39 } 40 } 41 42 // if majors are equal, then minor should be less or equal 43 // so we make sure module don't want any features we don't have 44 if moduleVersion.Minor() > compilerVersion.Minor() { 45 return &compiler.Error{ 46 Err: fmt.Errorf( 47 "%w: incompatible minors: module %v wants %v while current is %v", 48 ErrCompilerVersion, 49 modRef, mod.Manifest.LanguageVersion, a.compilerVersion, 50 ), 51 } 52 } 53 54 // at this point we sure we have same majors and got.Minor >= want.Minor 55 56 // if module's minor is less than ours then we don't care about patches 57 // because with newer minor we sure have all the patches of the previous one 58 if moduleVersion.Minor() < compilerVersion.Minor() { 59 // note that we don't fix previous minors and instead force to update 60 return nil 61 } 62 63 // if we here then we sure than minors are equal (as well as majors) 64 // this is the only case where we actually care about patches 65 66 // it's ok if we have some patches that module doesn't rely on 67 // but it's not ok if module a wants some patch we don't really have 68 if moduleVersion.Patch() > compilerVersion.Patch() { 69 return &compiler.Error{ 70 Err: fmt.Errorf( 71 "%w: incompatible patch: module %v wants %v while current is %v", 72 ErrCompilerVersion, 73 modRef, mod.Manifest.LanguageVersion, a.compilerVersion, 74 ), 75 } 76 } 77 78 // versions are strictly equal 79 return nil 80 }